同服务器部署React+FastAPI遭遇CORS跨域问题求助
问题场景
- 部署环境:Ubuntu 22.04.4 LTS,Node 18.19.1,Python 3.10.5,Nginx 1.18.0
- 架构:FastAPI后端运行在
http://localhost:8000,提供/api/v1接口;React前端运行在http://localhost:3000,本地测试接口调用正常 - 目标:通过
web.mydomain.com访问前端,同时让前端能调用同服务器上的后端API,使用Nginx做反向代理 - 遇到的错误:
Access to XMLHttpRequest at 'http://localhost:8000/api/v1/login/access_token' from origin 'http://web.mydomain.com' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space `local`.
错误原因
这个CORS错误不是普通跨域问题,是浏览器的私有网络访问限制:当页面运行在非安全上下文(比如HTTP而非HTTPS)的公网域名下,浏览器会阻止它访问localhost、127.0.0.1这类本地私有地址的资源,这是浏览器的安全策略,用于防范潜在攻击。
之前尝试的Nginx添加CORS头、webpack配置http-proxy-middleware无效,核心原因是前端请求的目标还是localhost:8000,本质触发的是浏览器的私有网络访问限制,而非普通跨域。
解决方案
核心思路是让前端调用同域名下的API路径,再通过Nginx将该路径反向代理到后端服务,彻底避免直接访问localhost。
1. 调整前端API请求地址
把前端中所有指向http://localhost:8000/api/v1的请求,改为相对路径/api/v1,或者完整路径http://web.mydomain.com/api/v1。
比如Axios配置修改:
// 之前的配置 axios.defaults.baseURL = 'http://localhost:8000/api/v1'; // 修改后的配置 axios.defaults.baseURL = '/api/v1';
2. 配置Nginx反向代理
修改Nginx站点配置文件(通常在/etc/nginx/sites-available/web.mydomain.com),将前端页面和API请求分别代理到对应服务:
server { listen 80; server_name web.mydomain.com; # 代理前端页面请求 location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 代理API请求到FastAPI后端 location /api/v1 { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 可选:如果后端需要识别原请求协议(比如后续升级HTTPS) proxy_set_header X-Forwarded-Proto $scheme; } }
3. 生效配置并验证
- 测试Nginx配置语法:
sudo nginx -t - 重新加载Nginx:
sudo systemctl reload nginx - 访问
http://web.mydomain.com,测试API调用是否正常
优化建议
升级到HTTPS:
浏览器的私有网络访问限制在HTTPS(安全上下文)下会放宽,建议用Let's Encrypt免费证书配置HTTPS,既提升站点安全性,也能避免后续类似限制。用环境变量区分开发/生产API地址:
避免硬编码API地址,通过环境变量区分开发和生产环境:# .env.development(开发环境) REACT_APP_API_BASE_URL=http://localhost:8000/api/v1 # .env.production(生产环境) REACT_APP_API_BASE_URL=/api/v1代码中使用:
axios.defaults.baseURL = process.env.REACT_APP_API_BASE_URL;给前端静态资源加缓存策略:
在Nginx配置中给前端静态资源添加缓存规则,提升页面加载速度:location ~* \.(js|css|png|jpg|svg)$ { proxy_pass http://localhost:3000; expires 30d; add_header Cache-Control "public, max-age=2592000"; }FastAPI的CORS配置(可选):
如果后续需要允许其他域名直接访问后端API,可以在FastAPI中配置CORS,但当前同域名代理场景下无需配置:from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["https://web.mydomain.com"], # 替换为你的生产域名 allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )
内容的提问来源于stack exchange,提问作者hellbreak

