Skip to content

nginx 跨域 CORS

注意

!> 如果后端例如 FastApi, Webhook 等已经配置过跨域, 那么 nginx 将无需再次配置跨域设置.

因为 Nginx 和服务端均对 Access-Control-Allow-Origin 标头设置了值,导致请求未通过浏览器的 CORS 策略,从而被浏览器拦截了响应结果。在平时项目开发中,尽量协调好一端去配置跨域策略,避免因重复设置标头而造成请求失败的问题。

配置

nginx
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
        add_header 'Access-Control-Max-Age' 1728000 always;
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain; charset=utf-8';

解决 OPTION 重复请求

nginx
        if ($request_method = 'OPTIONS') {
            return 204 ;
        }

多域名跨域

if (不推荐)

nginx
server {
set $allow_origin "";
if ( $http_origin ~ '^https?://(www|m).sundayle.com' ) {
      set $allow_origin $http_origin;
}
    location /{
        add_header 'Access-Control-Allow-Origin' $allow_origin;
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Token,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,X_Requested_With,If-Modified-Since,Cache-Control,Content-Type';
        if ($request_method = 'OPTIONS') {
            return 204;
        }
...
}

map (建议)

nginx
map $http_origin $allow_origin {
    default "";
    "~^(https?://localhost(:[0-9]+)?)" $1;
    "~^(https?://127.0.0.1(:[0-9]+)?)" $1; 
    "~^(https?://192.168.10.[\d]+(:[0-9]+)?)" $1; 
    "~^https://www.sunday.com" https://www.sundayle.com;
    "~^https://m.sundayle.com" https://m.sundayle.com;
    "~^(https?://[\w]+.open.sundayle.com)" $1;
    #"~^(https?://([\w]+.)?[\w]+.open.sundayle.com)" $1;  #允许一级和二级域名

}

server {
    location /{
        add_header 'Access-Control-Allow-Origin' $allow_origin;
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Token,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,X_Requested_With,If-Modified-Since,Cache-Control,Content-Type';
        if ($request_method = 'OPTIONS') {
            return 204;
        }
...
}

其他更多判断

nginx
location / {
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' 'https://www.sundayle.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 1728000; # 20days
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' 'https://www.sundayle.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' 'https://www.sundayle.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
}