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

Nginx反向代理上游服务器时Django出现CORS跨域问题,直接访问上游服务器则正常

Nginx反向代理上游服务器时Django出现CORS跨域问题,直接访问上游服务器则正常

遇到这种情况真的很挠头——明明直接访问上游服务器的IP或域名一切正常,通过Nginx反向代理就触发CORS错误,而且还是同一个应用部署,这大概率是代理过程中请求头传递+Django的Host验证在搞鬼,咱们一步步拆解解决:

核心原因分析

你目前的问题本质上可能不是CORS中间件的问题,而是:
当通过Nginx代理时,你配置了proxy_set_header Host $http_host;,这会把前端请求的api.example.com作为Host头传递给上游的Django服务器。但上游Django的ALLOWED_HOSTS里只加了api3.example.com和1.2.3.4,并没有包含api.example.com。

这时候Django会因为Host不在允许列表里,直接返回错误响应(你看到的404或400),而这个错误响应不会经过你的CORS中间件,自然就没有Access-Control-Allow-Origin这类跨域头,浏览器就会把这个错误识别为CORS问题。

而你直接访问上游服务器时,请求的Host是api3.example.com/1.2.3.4,正好在Django的允许列表里,所以应用正常处理请求,CORS中间件也能正确返回跨域头,自然就没问题。

解决方案步骤

1. 先解决Django的Host允许问题(最关键)

修改上游Django项目的settings.py,把代理域名api.example.com添加到ALLOWED_HOSTS里:

ALLOWED_HOSTS = ['api3.example.com', '1.2.3.4', 'api.example.com']
# 测试环境可以临时用 '*' 验证,但生产环境不建议这么做

修改后重启Django应用(比如uwsgi/gunicorn),再测试代理请求。

2. 优化Nginx的代理配置,确保请求头完整传递

在Nginx的location /块里,添加显式传递Origin头的配置,避免上游Django拿不到跨域请求的Origin信息:

location / {
    proxy_pass http://backend;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header REMOTE_ADDR $remote_addr;
    # 新增:传递Origin头给上游
    proxy_set_header Origin $http_origin;
    proxy_read_timeout 1000;
}

3. 可选:在Nginx层面直接处理CORS(更稳定)

如果你想彻底避免Django中间件的影响,可以在Nginx的server块里直接配置CORS规则,让Nginx来处理跨域请求,这样代理层就能直接响应OPTIONS预检请求,不需要透传给上游:

server {
    server_name api.example.com;
    # ... 你的其他配置(gzip、ssl等)

    # 先处理OPTIONS预检请求
    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Origin "*";
        add_header Access-Control-Allow-Methods "DELETE, GET, OPTIONS, PATCH, POST, PUT";
        add_header Access-Control-Allow-Headers "cache-control, accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with";
        add_header Access-Control-Max-Age 86400;
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }

    # 给其他请求添加CORS响应头
    add_header Access-Control-Allow-Origin "*";
    add_header Access-Control-Allow-Methods "DELETE, GET, OPTIONS, PATCH, POST, PUT";
    add_header Access-Control-Allow-Headers "cache-control, accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with";

    # ... 你的location配置
}

注意:Nginx里的if指令在某些场景下有坑,但处理OPTIONS请求这个场景是安全的。

验证步骤

  1. 先完成步骤1,重启Django后测试代理请求,看是否还会出现CORS错误;
  2. 如果还有问题,再添加步骤2的Origin头配置;
  3. 若还是不行,再尝试步骤3的Nginx层面CORS配置。

备注:内容来源于stack exchange,提问作者nadermx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 11:49:51