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

FastAPI/Nginx部署下CORS问题:响应头未正确设置

CORS配置问题排查:React + FastAPI + Nginx环境

技术栈

  • 前端:React(运行在localhost:5173)
  • 后端:FastAPI + Gunicorn(Unix Socket)
  • 反向代理:Nginx
  • 服务器:Digital Ocean Droplet

问题描述

前端(localhost:5173)向后端服务器(159.89.109.217)发起GET请求时触发CORS错误,尽管:

  • 请求返回状态码200
  • 服务器能正确返回JSON数据
  • Nginx和FastAPI都已配置CORS规则

当前配置

FastAPI CORS中间件配置

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Nginx配置

server {
listen 80 default_server;
listen [::]:80 default_server;

server_name _;
root /var/www/html;

location / {
    # 启用调试日志
    add_header X-Debug-Origin $http_origin always;
    add_header X-Debug-Host $host always;

    # CORS 响应头
    add_header 'Access-Control-Allow-Origin' 'http://localhost:5173' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' '*' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Max-Age' 1728000 always;

    proxy_pass http://unix:/run/gunicorn.sock;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' 'http://localhost:5173' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Max-Age' 1728000 always;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

已测试操作

  • 直接用curl请求服务器能正常获取正确数据
  • 配置的调试响应头未出现在返回结果中
  • 已确认服务器80端口防火墙处于开放状态
  • 多次调整FastAPI和Nginx的CORS配置
  • 浏览器报错信息:CORS Missing Allow Origin
  • 响应中仅包含access-control-allow-credentials: true,缺失Access-Control-Allow-Origin头

疑问

  1. 为什么已经在FastAPI和Nginx两处配置了CORS头,仍然无法正确生效?
  2. 配置的调试头为什么没有出现在响应里?
  3. 当前Nginx代理转发的配置下,CORS头传递是否存在已知问题?

问题分析与解决方案

核心问题

你的配置存在两个关键冲突点:

  1. allow_credentials=true与*源的冲突:浏览器强制要求,当启用allow_credentials时,Access-Control-Allow-Origin不能设为*,否则会判定该头无效,直接触发CORS错误。你在FastAPI中设置了allow_origins=["*"],这和Nginx的固定源配置冲突,且违反浏览器规则。
  2. Nginx if块的上下文隔离:Nginx的if块是独立上下文,里面的add_header会完全替换主location块的对应配置。如果请求触发了OPTIONS预检,if块里没添加调试头,就会导致调试头丢失;同时重复配置的CORS头也可能出现覆盖或遗漏。

修复步骤

步骤1:禁用FastAPI的CORS中间件

注释掉FastAPI中的CORSMiddleware代码,避免多层面配置冲突,统一在Nginx处理CORS逻辑。

步骤2:修正Nginx配置

使用map指令动态匹配允许的源,避免硬编码,同时解决if块的上下文问题:

server {
listen 80 default_server;
listen [::]:80 default_server;

server_name _;
root /var/www/html;

# 定义允许的请求源,可按需添加多个规则
map $http_origin $allowed_origin {
    ~^http://localhost:5173$ $http_origin;
    # 示例:添加生产环境域名
    # ~^https://your-production-domain.com$ $http_origin;
}

location / {
    # 调试头,确保在所有请求上下文都生效
    add_header X-Debug-Origin $http_origin always;
    add_header X-Debug-Host $host always;

    # CORS响应头,仅当请求源在允许列表时返回
    add_header 'Access-Control-Allow-Origin' $allowed_origin always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' '*' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Max-Age' 1728000 always;

    proxy_pass http://unix:/run/gunicorn.sock;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    if ($request_method = 'OPTIONS') {
        # 预检请求直接返回204,复用上方的CORS头配置,无需重复编写
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

步骤3:重新加载Nginx配置

执行命令验证配置并重启服务:

sudo nginx -t && sudo systemctl reload nginx

步骤4:验证修复

清除浏览器缓存后重新发起请求,查看响应头:

  • 确认Access-Control-Allow-Origin正确显示为http://localhost:5173
  • 调试头X-Debug-Origin和X-Debug-Host正常出现
  • 浏览器不再报CORS错误

额外说明

  • 启用allow_credentials时,必须明确指定允许的源,不能使用通配符*,这是浏览器的安全规则
  • 使用Nginx的map指令管理允许的源,比多个if块更高效且易维护
  • 尽量避免在多个服务层面配置CORS,否则容易出现头优先级冲突或遗漏问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:24:56