Nginx启用HTTPS后CORS报错问题求助
HTTPS升级后Nginx CORS请求失败问题
问题背景
此前CORS功能正常,但将api.MYDOMAIN的Nginx配置切换为HTTPS后,CORS请求失败。现有两台AWS EC2实例:
MYDOMAIN(主域名实例)api.MYDOMAIN(子域名实例,与主域名使用不同SSL证书)
已在api.MYDOMAIN的安全组中配置允许主域名IP的HTTPS入站规则,且通过curl https://api.MYDOMAIN/healthcheck可正常访问API,仅CORS请求失败。
Nginx配置
map $http_origin $cors_origin { ~^https?://(www.)?MYDOMAIN$ $http_origin; default ""; } map "$cors_origin" $cors_cred { ~^$ false; default true; } map "$request_method" $cors_method { ~^OPTIONS$ true; ~^GET$ true; ~^DELETE$ true; ~^PATCH$ true; ~^POST$ true; ~^PUT$ true; default false; } # echo into log to test variables log_format upstream_time "$time_local http_origin=$http_origin remote_addr=$remote_addr allow_origin=$cors_origin cred=$cors_cred cors_method=$cors_method request_method=$request_method"; server { listen 80; server_name *.MYDOMAIN; return 301 https://$host$request_uri; } server { listen 443 ssl; ssl_certificate /etc/letsencrypt/live/api.MYDOMAIN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.MYDOMAIN/privkey.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; server_name api.MYDOMAIN; location / { access_log /var/log/nginx/access.log upstream_time; if ($cors_origin) { add_header 'Access-Control-Allow-Credentials' $cors_cred always; add_header 'Access-Control-Allow-Origin' $cors_origin always; add_header 'Access-Control-Allow-Methods' 'GET, DELETE, PATCH, POST, PUT, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Accept, Authorization, Keep-Alive, Origin, DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; } if ($request_method = 'OPTIONS') { # Tell client that this pre-flight info is valid for 20 days add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } # test # root /var/www/html; index index.html; proxy_pass http://localhost:8081; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } # End location } # End server
访问日志
19/Aug/2024:20:45:11 +0000 http_origin=https://www.MYDOMAIN remote_addr=MYIP allow_origin=https://www.MYDOMAIN cred=true cors_method=true request_method=OPTIONS
Node服务代码(server.ts)
import Fastify from "fastify"; import fs from "fs"; import path from "path"; const server = Fastify(); server.get("/healthcheck", (req, res) => { res.send({ message: "Success" }); }); // graceful shutdown const listeners = ["SIGINT", "SIGTERM"]; listeners.forEach((signal) => { process.on(signal, async () => { await server.close(); process.exit(0); }); }); const init = async () => { const options = { port: 8081, }; server.listen(options, (err, address) => { if (err) { console.error(err); process.exit(1); } console.log(`Server listening at ${address}`); }); };
排查与解决建议
修正正则匹配规则:当前
map $http_origin $cors_origin中的正则~^https?://(www.)?MYDOMAIN$存在语法问题,www.里的点是元字符,会匹配任意单个字符,应修改为~^https?://(www\.)?MYDOMAIN$,确保只匹配带www.前缀的主域名。检查OPTIONS响应头覆盖问题:当前配置中,OPTIONS请求会进入第二个
if块直接返回204,可能导致第一个if块的CORS头未被正确添加。可以将CORS头逻辑整合到OPTIONS处理块:
if ($request_method = 'OPTIONS') { if ($cors_origin) { add_header 'Access-Control-Allow-Credentials' $cors_cred always; add_header 'Access-Control-Allow-Origin' $cors_origin always; add_header 'Access-Control-Allow-Methods' 'GET, DELETE, PATCH, POST, PUT, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Accept, Authorization, Keep-Alive, Origin, DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; } add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; }
- 模拟OPTIONS请求验证响应头:用curl模拟预请求,检查响应是否包含正确的CORS头:
curl -X OPTIONS -H "Origin: https://www.MYDOMAIN" -H "Access-Control-Request-Method: GET" -v https://api.MYDOMAIN/healthcheck
- 查看浏览器控制台错误:打开浏览器开发者工具控制台,获取具体的CORS错误提示(如Origin不允许、Credentials头缺失等),精准定位问题。
内容的提问来源于stack exchange,提问作者Inspiraller
相关产品推荐
相关产品推荐

