为什么 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 响应如预期的那样再次开始工作。
我在 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 响应如预期的那样再次开始工作。