You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}`);
  });
};

排查与解决建议

  1. 修正正则匹配规则:当前map $http_origin $cors_origin中的正则~^https?://(www.)?MYDOMAIN$存在语法问题,www.里的点是元字符,会匹配任意单个字符,应修改为~^https?://(www\.)?MYDOMAIN$,确保只匹配带www.前缀的主域名。

  2. 检查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;
}
  1. 模拟OPTIONS请求验证响应头:用curl模拟预请求,检查响应是否包含正确的CORS头:
curl -X OPTIONS -H "Origin: https://www.MYDOMAIN" -H "Access-Control-Request-Method: GET" -v https://api.MYDOMAIN/healthcheck
  1. 查看浏览器控制台错误:打开浏览器开发者工具控制台,获取具体的CORS错误提示(如Origin不允许、Credentials头缺失等),精准定位问题。

内容的提问来源于stack exchange,提问作者Inspiraller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 11:34:50