部署在独立Cloud Run实例的FastAPI与Vue无法协商CORS问题
问题:FastAPI + Vue 部署Cloud Run后跨域请求失败
本地同一机器容器化运行时,FastAPI后端与Vue前端通信正常,但部署到Google Cloud的Cloud Run独立实例后,浏览器无法完成跨域协商,提示Access-Control-Allow-Origin头缺失。
相关代码片段
FastAPI主文件
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() # 跨域中间件配置 origins = [ "http://localhost", "http://localhost:8080", "http://127.0.0.1", "http://127.0.0.1:8080", "https://api.domain.com", # Cloud Run后端域名 "https://alpha.domain.com", # Cloud Run前端域名 ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_origin_regex='https?://.*', # 本以为这是万能解决方案? allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )
Vue main.js
import 'bootstrap/dist/css/bootstrap.css'; import { createApp } from "vue"; import axios from 'axios'; import App from './App.vue'; import router from './router'; import store from './store'; const app = createApp(App); axios.defaults.withCredentials = true; // axios.defaults.baseURL = "http://localhost:8000"; // 本地测试地址 console.log("Defaulting to GCP location: https://api.domain.com/"); axios.defaults.baseURL = "https://api.domain.com/"; app.use(router); app.use(store); app.mount("#app");
Vue vue.config.js
const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true })
已尝试的操作
- 在FastAPI的CORS配置中使用通配符
- 调整多种baseURL配置
- 将所有服务置于负载均衡后并使用生产域名
- 在Vue中添加DevServer的allowedHosts通配符配置
报错信息
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.domain.com/ping. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.
Axios的GET和POST请求均无法正常工作。
解决方案
1. 强制CORS中间件加载顺序
FastAPI的中间件必须在所有路由定义之前添加,否则中间件不会对路由生效,无法返回CORS响应头。
修正后的代码结构:
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() # 先配置CORS中间件 origins = [ "https://alpha.domain.com", # 仅保留前端生产域名,本地环境可通过环境变量动态添加 ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 再定义所有路由 @app.get("/ping") async def ping(): return {"message": "pong"}
2. 移除冲突的allow_origin_regex配置
当allow_credentials=True时,浏览器禁止Access-Control-Allow-Origin设为通配符*。即使配置了allow_origin_regex='https?://.*',FastAPI可能返回通配符头,导致跨域拦截。直接删除该配置,明确指定允许的前端域名即可。
3. 检查Cloud Run与负载均衡配置
- 确认Cloud Run后端服务的Ingress设置为
All,或者限制为前端服务的IP范围,避免请求被拦截。 - 检查负载均衡的转发规则,确保
Origin请求头未被修改或丢弃——FastAPI需要通过Origin头识别请求来源,才能返回对应的CORS头。
4. 验证后端响应头
用curl命令直接测试后端接口,确认是否返回正确的CORS头:
curl -H "Origin: https://alpha.domain.com" -I https://api.domain.com/ping
如果响应头中没有Access-Control-Allow-Origin: https://alpha.domain.com,说明CORS中间件未生效,回到第一步检查加载顺序。
5. Vue端优化
- 确保
axios.defaults.withCredentials = true仅在生产环境启用,避免本地测试时的不必要跨域问题。 - 前端必须使用绑定的自定义域名(如
https://alpha.domain.com),不要使用Cloud Run的临时默认域名,临时域名可能存在跨域限制。
内容的提问来源于stack exchange,提问作者Vincent Brandon
相关产品推荐
相关产品推荐

