响应头设置 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; 是不是预检请求就会返回200了?

不一定。仅设置:

add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;

并不能保证预检请求(OPTIONS)会返回 200,原因如下:


❌ 问题核心:Nginx 默认不会处理 OPTIONS 请求

在 Nginx 中,如果你没有显式为 OPTIONS 请求配置一个能返回 200 状态码 的处理逻辑,那么:

  • 即使你设置了 add_header ... always;
  • 如果后端(或 Nginx 配置)对 OPTIONS 请求返回的是 405 Method Not Allowed404
  • 那么浏览器收到的仍然是 非 200 响应,预检失败,实际请求被阻止。

💡 add_header ... always 只是“如果响应被发送,就加上这个头”,但它不能改变响应状态码


✅ 正确做法:显式处理 OPTIONS 请求并返回 200

你需要在 Nginx 配置中主动拦截 OPTIONS 请求,返回 200 + CORS 头:

location / {
    # 处理预检请求
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
        add_header 'Access-Control-Max-Age' 1728000; # 20天缓存预检
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;  # 或 return 200;
    }

    # 实际请求的 CORS 头(非预检)
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;

    # 你的代理或静态文件逻辑
    proxy_pass http://backend;
}

🔔 推荐使用 return 204;(No Content),因为预检响应通常不需要 body。


📌 关键点总结

问题 说明
❌ 仅加 add_header 不会改变 OPTIONS 请求的状态码(可能仍是 405)
✅ 必须 return 200/204 显式返回成功状态,浏览器才认为预检通过
✅ 需包含必要 CORS 头 Allow-OriginAllow-MethodsAllow-Headers(如果前端用了自定义头)
✅ 使用 if ($request_method = 'OPTIONS') 在 Nginx 中拦截预检请求

🔍 如何验证?

用 curl 测试:

curl -H "Origin: https://example.com" \
     -H "Access-Control-Request-Method: POST" \
     -H "Access-Control-Request-Headers: Authorization" \
     -X OPTIONS \
     http://your-api.com/some-path

你应该看到:

  • 状态码:204200
  • 响应头包含:Access-Control-Allow-MethodsAccess-Control-Allow-Headers

✅ 结论

只设置 add_header 'Access-Control-Allow-Methods' ... always; 是不够的!
你必须显式处理 OPTIONS 请求并返回 200/204,否则预检会失败。

这是 Nginx 配置 CORS 时最常见的误区之一。

posted @ 2026-02-05 10:31  龙陌  阅读(11)  评论(0)    收藏  举报