Google Cloud部署的Python Flask API跨域(CORS)问题求助
解决部署在Google Cloud上的Flask API跨域(CORS)问题
问题现象
跨域调用API时触发CORS拦截,报错信息:
Access to XMLHttpRequest at 'https://myapi.app/ask_question' from origin 'http://localhost:4200' (or 'https://mywebsite.dev') has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
前端调用代码(Angular)
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; interface ChatMessage { text: string; isUserMessage: boolean; } @Component({ selector: 'app-chatbot', templateUrl: './chatbot.component.html', styleUrls: ['./chatbot.component.css'] }) export class ChatbotComponent { isChatbotCollapsed = false; userInput: string = ''; chatMessages: ChatMessage[] = []; constructor(private http: HttpClient) {} sendMessage() { const userMessage = this.userInput; this.chatMessages.push({ text: userMessage, isUserMessage: true }); const apiUrl = 'https://myapi.app/ask_question'; //const apiUrl = 'http://127.0.0.1:5000/ask_question'; const payload = { input: userMessage }; this.http.post(apiUrl, payload).subscribe(response => { const apiResponse = response as { output: string }; const botResponse = apiResponse.output; this.chatMessages.push({ text: botResponse, isUserMessage: false }); }); this.userInput = ''; } }
后端Flask API代码(原代码)
import json import os from flask import Flask, request from flask_cors import CORS app = Flask(__name__) CORS(app, resources={r"/*": {"origins":"https://mywebsite.dev"}}) @app.route('/ask_question', methods=['POST', 'OPTIONS']) def ask_question(): if request.method == 'OPTIONS': response = make_response() response.headers.add('Access-Control-Allow-Origin', 'https://mywebsite.dev') response.headers.add('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') response.headers.add('Access-Control-Allow-Headers', 'Content-Type') return response data = request.get_json() input_string = data['input'] output = 'hello, you said' + input_string response = make_response({'output': output}) response.headers.add('Access-Control-Allow-Origin', 'https://mywebsite.dev') response.headers.add('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') response.headers.add('Access-Control-Allow-Headers', 'Content-Type') return response if __name__ == '__main__': app.run()
已尝试但无效的方案
- 明确配置域名:
或CORS(app, resources={r"*": {"origins": "*"}})CORS(app, resources={r"/*": {"origins": ["https://mywebsite.dev/", "https://mywebsite.firebaseapp.com/"]}}) - 添加响应头:
@app.after_request def add_cors_headers(response): response.headers['Access-Control-Allow-Origin'] = 'https://mywebsite.dev' response.headers['Access-Control-Allow-Headers'] = 'Content-Type' response.headers['Access-Control-Allow-Methods'] = 'POST' return response - 在Google Cloud中配置CORS环境变量
问题根源与解决方案
关键错误点
- 缺少
make_response导入:原代码中使用make_response但未从flask模块导入,导致运行时抛出异常,无法生成带有正确CORS头的响应。 - CORS配置重复冲突:同时使用
flask-cors库和手动处理OPTIONS请求、添加响应头,容易导致头信息混乱,不符合浏览器的CORS校验规则。 - Google Cloud部署层可能覆盖响应头:如果API部署在Cloud Run、App Engine等平台,平台自身的配置可能会覆盖代码中设置的响应头。
修正后的Flask代码
import json import os from flask import Flask, request, make_response # 补充导入make_response from flask_cors import CORS app = Flask(__name__) # 允许生产域名和本地开发环境的跨域请求 CORS(app, resources={r"/*": {"origins": ["https://mywebsite.dev", "http://localhost:4200"]}}) @app.route('/ask_question', methods=['POST']) def ask_question(): data = request.get_json() input_string = data['input'] output = 'hello, you said ' + input_string # Flask会借助flask-cors自动添加正确的CORS响应头,无需手动处理 return {'output': output} if __name__ == '__main__': app.run()
部署环境补充配置
若使用Cloud Run:
在服务的编辑与部署新版本页面,进入「容器」→「高级设置」→「CORS」:
- 允许的来源:
https://mywebsite.dev,http://localhost:4200 - 允许的方法:
POST,OPTIONS - 允许的头:
Content-Type
若使用App Engine:
在app.yaml中添加CORS配置:
handlers: - url: /.* script: auto http_headers: Access-Control-Allow-Origin: "https://mywebsite.dev http://localhost:4200" Access-Control-Allow-Methods: "POST, OPTIONS" Access-Control-Allow-Headers: "Content-Type"
依赖确认
确保requirements.txt包含flask-cors:
flask flask-cors
内容的提问来源于stack exchange,提问作者Jérémie Chassin
相关产品推荐
相关产品推荐

