FastAPI部署至EC2后CORS配置无效且请求未到达后端问题求助
我遇到了一个特别头疼的问题:本地运行完全正常的FastAPI代码,部署到EC2服务器后,哪怕反复调整CORS跨域配置,始终报CORS错误。我已经花了2个小时死磕请求的Origin地址——不管是从前端页面直接复制的、还是浏览器控制台CORS错误里明确显示的,都已经加到了允许列表里,带尾斜杠的、不带的,甚至子域名通配、.amazonaws.com这种后缀通配都试过了,连最宽松的"*"也试了(但网上说"*"太开放可能失效,后来又去掉了)。
网上大部分解决方案都强调要使用精确的Origin地址,但我已经核对了无数次,确定地址完全正确,可问题还是没解决。更奇怪的是,后端日志里完全看不到请求记录,浏览器控制台一直提示Access to fetch at 'http://localhost:8000/uploadfile/' from origin 'http://ec2-mymachine.us-east-2.compute.amazonaws.com:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource。
想请教各位,除了核对Origin地址,还有什么其他可以尝试的方向吗?
我的后端代码(已替换真实EC2主机名为ec2-mymachine.us-east-2.compute.amazonaws.com,已多次确认真实主机名无误):
import os from fastapi import FastAPI, UploadFile, File from fastapi.responses import FileResponse from fastapi.middleware.cors import CORSMiddleware origins = [ "0.0.0.0:5173", "http://ec2-mymachine.us-east-2.compute.amazonaws.com:5173/", "http://ec2-mymachine.us-east-2.compute.amazonaws.com:5173", ".ec2-mymachine.us-east-2.compute.amazonaws.com:5173/", ".ec2-mymachine.us-east-2.compute.amazonaws.com:5173", ".amazonaws.com:5173/", ".amazonaws.com:5173", ] upload_folder = "./data/images" app = FastAPI(debug=True) app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"] ) @app.get("/", tags=["root"]) async def read_root() -> dict: return {"message": "This is the Xoori MVP app."} @app.get("/images/{image_name}") async def get_image(image_name: str): image_path = f"{upload_folder}/{image_name}" return FileResponse(image_path) @app.post("/uploadfile/") async def create_upload_file(file: UploadFile = File(...)): print(f"DEBUG: Received file: {file.filename}, Content-Type: {file.content_type}") file_location = os.path.join(upload_folder, file.filename) with open(file_location, "wb") as f: f.write(await file.read()) return {"filename": file.filename, "content_type": file.content_type}
前端上传逻辑代码片段:
const handleUpload = async () => { if (!selectedFile) return; setUploading(true); const formData = new FormData(); formData.append("file", selectedFile); // "file" 与FastAPI接口参数名一致 try { const response = await fetch("http://localhost:8000/uploadfile/", { // 这里的URL有问题! method: "POST", body: formData, }); if (response.ok) { setUploadSuccess(true); setSelectedFile(null); // 上传成功后清空文件 } else { console.error("Upload failed"); setUploadSuccess(false); } } catch (error) { console.error("Error during upload:", error); setUploadSuccess(false); } finally { setUploading(false); } };
后端日志(无任何请求记录):
INFO: Will watch for changes in these directories: ['/home/ubuntu/workspace/holocene/backend'] INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: Started reloader process [304522] using StatReload INFO: Started server process [304524] INFO: Waiting for application startup. INFO: Application startup complete.
针对问题的排查与解决建议:
1. 修复前端请求地址(最核心的错误!)
你前端代码里的fetch目标写的是http://localhost:8000/uploadfile/,这是致命问题:
- 当用户在浏览器中访问EC2的
http://ec2-mymachine.us-east-2.compute.amazonaws.com:5173时,浏览器上下文里的localhost指的是用户自己的本地电脑,而不是EC2服务器。所以你的请求根本没发到EC2上的FastAPI后端,这就是后端日志完全没记录请求的原因! - 必须把前端的请求地址改成EC2后端的公网地址,比如:
const response = await fetch("http://ec2-mymachine.us-east-2.compute.amazonaws.com:8000/uploadfile/", {
2. 简化CORS Origins配置,避免无效通配符
FastAPI的CORSMiddleware(基于Starlette)不支持*.example.com这种子域名通配符格式,只能使用精确的Origin地址,或者全局通配符"*"(但"*"和allow_credentials=True不能同时使用,浏览器会直接拦截这种冲突配置)。
建议先把origins列表简化成只保留精确的前端地址,测试正常后再按需扩展:
origins = [ "http://ec2-mymachine.us-east-2.compute.amazonaws.com:5173", ]
3. 检查EC2安全组与网络连通性
- 确保EC2的安全组已经开放8000端口的入站权限,允许来自前端IP(或临时允许
0.0.0.0/0用于测试)的TCP请求。 - 验证后端的可访问性:在本地终端执行
curl http://ec2-mymachine.us-east-2.compute.amazonaws.com:8000/,如果能返回{"message": "This is the Xoori MVP app."},说明后端网络是通的。
4. 清除浏览器缓存测试
浏览器有时会缓存旧的CORS响应,建议使用无痕模式测试,或者手动清除浏览器缓存后再尝试上传。
内容来源于stack exchange

