为什么 CORS 适用于 API 请求,但不适用于我的 Nginx 配置中的媒体文件(例如 mp4、webm)?

Why is CORS working for API requests but not media files (e.g. mp4, webm) on my Nginx config?

我在 Ubuntu 上设置了一个 Nginx 服务器,为两个网站提供服务。一个是交付其 API 内容的 Wordpress,另一个是使用 Axios 使用 API 的前端应用程序。

我可以从 API 查询和读取 JSON 内容,并检查响应 headers 是否与我的 CORS 配置匹配。但是在 Chrome,我在控制台中收到应用程序在从 API 内容中读取 URI 后尝试使用的所有媒体文件(.mp4、.webm)上的 CORS 错误。

Access to video at 'https://api.example.com/wp-content/uploads/2019/05/Seiho-Edited_compress.mp4' 
from origin 'https://next.example.com' 
has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

它在 Firefox 上正常运行。

请注意,在 Chrome 的地址栏中粘贴媒体 URI 会按预期显示媒体。也不是视频标签使用 crossorigin="anonymous".

我做错了什么?

以下是我的 Nginx 配置,以防我遗漏了一些明显的问题。

server {
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    root /var/www/example.com/backend;
    server_name api.example.com;
    access_log /var/log/nginx/unicorn_access.log;
    error_log /var/log/nginx/unicorn_error.log;

    charset                     utf-8;
    gzip                        off;

    # Set CORS policy
    set $cors_origin            "";
    set $cors_cred              "";
    set $cors_header            "";
    set $cors_method            "";

    if ($http_origin ~ '^https?:\/\/(localhost|next.example\.com)$') {
        set $cors_origin        $http_origin;
        set $cors_cred          true;
        set $cors_header        $http_access_control_request_headers;
        set $cors_method        $http_access_control_request_method;
    }

    add_header Access-Control-Allow-Origin      $cors_origin;
    add_header Access-Control-Allow-Credentials $cors_cred;
    add_header Access-Control-Allow-Headers     $cors_header;
    add_header Access-Control-Allow-Methods     $cors_method;

    location / {
        index                   index.php index.html;
        try_files               $uri $uri/ /index.php?$args;
    }

    client_max_body_size        50m;

    # Add trailing slash to */wp-admin requests.
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

    # Prevents hidden files (beginning with a period) from being served
    location ~ /\. {
        access_log              off;
        log_not_found           off;
        deny                    all;
    }

    # Send 'expires' headers and turn off 404 logging
    location ~* ^.+.(xml|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log              off;
        log_not_found           off;
        expires                 max;
    }

    # Pass all .php files onto a php-fpm or php-cgi server
    location ~ \.php$ {
        try_files               $uri =404;
        include                 /etc/nginx/fastcgi_params;
        fastcgi_read_timeout    3600s;
        fastcgi_buffer_size     128k;
        fastcgi_buffers         4 128k;
        fastcgi_param           SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass            unix:/run/php/php7.2-fpm.sock;
        fastcgi_index           index.php;
    }

    # Robots
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # Restrictions
    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }
}

配置没有错误。

我尝试 运行在没有 add-ons 的新 Chrome 用户配置文件上成功地安装了该应用程序。然后我设法 运行 在我的主要 Chrome 个人资料 删除了我所有的 cookies 之后。我无法解释其背后的基本原理,但它确实有效。在我使用的插件中,我还没有找到罪魁祸首,但我正在关闭这个问题,因为这与 Nginx 无关。

没有适当的 CORS/Access-Control-* headers.

的错误响应很常见

下次 运行 进入此页面时,打开浏览器的开发人员工具并检查 HTTP 响应。您可能会看到一些错误状态,而不是 2xx.

您提到清除 cookie 解决了该问题。我猜测您的应用程序上游存在一些错误,清除 cookie 只是解决了该错误情况。因此,CORS 响应如预期的那样再次开始工作。