Nginx反向代理Jelastic服务器时仅PUT/POST请求出现CORS错误
解决Jelastic环境下Nginx 1.24.0 HTTP3/QUIC的CORS问题
问题现象
- 原有Jelastic服务器运行正常,添加Nginx流量分发器后,GET请求与登录POST请求可正常工作,但登录后的POST、PUT请求出现CORS错误(预检OPTIONS请求正常,仅实际请求报错)
- Firefox、Linux设备均出现相同错误,Safari可正常运行
- 关闭Chrome的QUIC协议后,错误消失;直接使用Nginx负载均衡器无此问题,仅在Jelastic流量分发器下出现
错误详情
CORS报错信息
Access to XMLHttpRequest at '' from origin 'xyz' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
错误响应头(状态码500)
Content-Length: 383 Content-Type: text/html Date: Thu, 20 Jul 2023 11:46:56 GMT Etag: "6194d09a-17f" Server: nginx
Safari正常响应头特征
包含Access-Control-Allow-Origin: *等完整CORS头
不同浏览器请求对比
Brave/Chrome(使用HTTP3/QUIC)请求
curl 'https://dev-backend.xyz.app/api/collections/722/collectibles/4708' \ -X 'PUT' \ -H 'authority: dev-backend.xyz.app' \ -H 'accept: application/json, text/plain, */*' \ -H 'accept-language: en-GB,en;q=0.9' \ -H 'authorization: Bearer abcdef' \ -H 'content-type: application/json' \ -H 'origin: https://dev.xyz.app' \ -H 'referer: https://dev.xyz.app/' \ -H 'sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Brave";v="114"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "macOS"' \ -H 'sec-fetch-dest: empty' \ -H 'sec-fetch-mode: cors' \ -H 'sec-fetch-site: same-site' \ -H 'sec-gpc: 1' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \ --data-raw '{jsondata}'
Safari(使用HTTP2)请求
curl 'https://dev-backend.xyz.app/api/collections/722/collectibles/4708' \ -X 'PUT' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/plain, */*' \ -H 'Authorization: Bearer abcdef' \ -H 'Sec-Fetch-Site: same-site' \ -H 'Accept-Language: en-GB,en;q=0.9' \ -H 'Accept-Encoding: gzip, deflate, br' \ -H 'Sec-Fetch-Mode: cors' \ -H 'Host: dev-backend.xyz.app' \ -H 'Origin: https://dev.xyz.app' \ -H 'Content-Length: 944' \ -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Safari/605.1.15' \ -H 'Referer: https://dev.xyz.app/' \ -H 'Connection: keep-alive' \ -H 'Sec-Fetch-Dest: empty' \ --data-binary '{jsondata}'
当前Nginx配置
location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept'; add_header 'Access-Control-Max-Age' 86400; return 204; } add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Headers' 'Range, Authorization, Content-Type, x-session-token'; add_header 'Access-Control-Max-Age' 3600; proxy_pass http://common; }
解决建议
- 强制所有响应添加CORS头
Nginx默认仅在2xx/3xx响应中执行add_header,而当前错误响应为500状态码,导致CORS头未被添加。需添加always参数确保无论响应状态如何都注入头信息:location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Range, x-session-token' always; add_header 'Access-Control-Max-Age' 86400 always; return 204; } add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Range, x-session-token' always; add_header 'Access-Control-Max-Age' 3600 always; proxy_pass http://common; } - 验证Jelastic流量分发器的HTTP3头传递
由于直接使用Nginx负载均衡器无问题,需确认Jelastic流量分发器是否完整转发HTTP3请求的Origin头。可在Nginx中添加日志记录$http_origin,验证HTTP3请求的Origin值是否正确:log_format cors_log '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_origin"'; access_log /var/log/nginx/cors_access.log cors_log; - 统一CORS配置规则
目前OPTIONS请求与普通请求的Access-Control-Allow-Headers配置不一致,建议统一设置,避免因头信息不匹配引发的问题。
内容的提问来源于stack exchange,提问作者halster
相关产品推荐
相关产品推荐

