【发布时间】:2017-06-10 22:37:06
【问题描述】:
我有一个 nginx 容器用作负载平衡器,用于基于流式 DASH 的服务。还有 3 个 VM 用作上游服务器。 这是 nginx 配置文件:
upstream cdn-audio {
server 192.168.99.103:9500;
server 192.168.99.104:9500;
server 192.168.99.105:9500;
}
upstream cdn-video {
server 192.168.99.103:9500;
server 192.168.99.104:9500;
server 192.168.99.105:9500;
}
server {
listen 80;
server_name 172.17.0.1;
access_log /var/log/nginx/acces.log main;
location = /LynyrdSkynyrdFreebirdAudio.mp4 {
# proxy_pass http://192.168.99.103:9500;
# proxy_pass http://cdn-audio/LynyrdSkynyrdFreebirdAudio.mp4;
add_header X-Upstream $upstream_addr;
add_header Host $host;
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin '*';
add_header Access-Control-Allow-Headers "Authorization,Range";
add_header Access-Control-Allow-Credentials "true";
add_header Content-Length 0;
add_header Content-Type text/plain;
add_header Host $host;
return 200;
}
return 302 $scheme://cdn-audio/LynyrdSkynyrdFreebirdAudio.mp4;
}
location = /LynyrdSkynyrdFreebirdVideo.mp4 {
add_header X-Upstream $upstream_addr;
# proxy_pass http://cdn-audio/LynyrdSkynyrdFreebirdVideo.mp4;
add_header Host $host;
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin '*' ;
add_header Access-Control-Allow-Headers "Authorization,Range";
add_header Access-Control-Allow-Credentials "true";
add_header Content-Length 0;
add_header Content-Type text/plain;
add_header Host $host;
return 200;
}
# proxy_pass http://cdn-video$request_uri;
# proxy_pass http://192.168.99.103:9500;
return 302 $scheme://cdn-video/LynyrdSkynyrdFreebirdVideo.mp4;
# add_header X-Upstream $upstream_addr;
}
}
从托管在另一个容器(前端容器)中的 html 页面,首先有一个 HTTP OPTIONS 请求到 :/LynyrdSkynyrdFreebirdAudio.mp4 和 :/LynyrdSkynyrdFreebirdVideo.mp4,因为跨站点来源。 然后响应头显示在配置代码中。
然后,当我尝试将请求重定向到我的三个上游服务器之一时,出现错误:
- XMLHttpRequest 无法加载 http://localhost:9200/LynyrdSkynyrdFreebirdVideo.mp4。重定向自 'http://localhost:9200/LynyrdSkynyrdFreebirdVideo.mp4' 到 'http://cdn-video/LynyrdSkynyrdFreebirdVideo.mp4' 已被阻止 CORS 政策:请求需要预检,这是不允许的 遵循跨域重定向。
- XMLHttpRequest 无法加载 http://localhost:9200/LynyrdSkynyrdFreebirdAudio.mp4。重定向自 'http://localhost:9200/LynyrdSkynyrdFreebirdAudio.mp4' 到 'http://cdn-audio/LynyrdSkynyrdFreebirdAudio.mp4' 已被阻止 CORS 政策:请求需要预检,这是不允许的 遵循跨域重定向。
请注意我做了
curl -I -X OPTIONS http://192.168.99.103:9500/LynyrdSkynyrdFreebirdAudio.mp4
这是回复:
HTTP/1.1 200 OK
Server: nginx/1.11.8
Date: Wed, 25 Jan 2017 16:31:28 GMT
Content-Length: 0
Connection: keep-alive
Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Range
你能帮我解决这个问题吗?
【问题讨论】:
-
你明白为什么你的浏览器会发送 OPTIONS 预检请求而不是直接发送实际请求吗?这通常仅在您向请求添加自定义标头或将请求的内容类型设置为特定值时才会发生。您可能只需对您的请求进行一些调整即可避免 OPTIONS 预检(例如,从中删除可能添加的任何不必要的标头)。
-
这是我的架构:我在一个容器中有一个前端 html+js;负载均衡器容器; N VM 作为 CDN。首先,我用前端 html 指向 l.b:这会导致 OPTIONS 预检请求,因为这是一个跨站点源请求。如果在 l.b. 中,我使用 proxy_pass 指令(返回 302 等),在第一个 OPTIONS 请求之后,我可以通过 HTTP GET 访问内容。如果我使用返回 302 等,在这个 HTTP 选项(响应正确)之后,我从浏览器的网络控制台看到很多 GET 和 302 响应......以及我在上面发布的错误。我认为这个错误是由返回 302 引起的。
-
这是一个跨站点请求的事实并不是导致发送 OPTIONS 的原因。 Lots of cross-site requests do not cause an OPTIONS request。触发发送 OPTIONS 的是您发送的特定请求的特定性质:如果它包含定义为 CORS-safelisted request-headers 的标题以外的标题,则只有这样才会发送 OPTIONS。因此,您可以通过从请求中删除一些标头来避免 OPTIONS。
标签: nginx cors load-balancing