Flask跨域请求(CORS)受阻问题求助
解决Flask CORS预请求404及跨域拦截问题
你的问题核心在于浏览器发送的OPTIONS预请求返回404,导致CORS检查直接失败,后续业务逻辑的响应头根本没机会生效。我们一步步拆解问题并解决:
问题根源分析
从日志和错误信息能看出两个关键问题:
- 浏览器请求的是
OPTIONS /chat/(带尾斜杠),但你的路由是@app.route("/chat")(不带尾斜杠),Flask默认严格匹配路由,所以这个请求找不到处理函数,直接返回404。 - 预请求是浏览器自动触发的前置检查,它失败的话,浏览器会直接拦截后续的业务请求,你后来添加的CORS响应头根本没机会被浏览器读到。
解决方案
下面是两种可靠的解决方式,选一种即可:
方式一:用Flask-CORS正确配置(推荐)
Flask-CORS库本身就能自动处理OPTIONS预请求,你只需要修正路径匹配和路由设置:
from flask import Flask, request, jsonify from flask_cors import CORS, cross_origin app = Flask(__name__) # 配置CORS:允许来自localhost:8080的请求,匹配/chat及带尾斜杠的/chat/ CORS(app, resources={r"/chat/*": {"origins": "http://localhost:8080"}}) # 开启strict_slashes=False,让/chat和/chat/都能匹配到该路由 @app.route("/chat", methods=["GET", "POST"], strict_slashes=False) def chat(): # 用request.get_json()自动解析JSON请求体,比手动load更简洁安全 data = request.get_json() if not data or 'message' not in data: return jsonify({'error': 'Missing message parameter'}), 400 response = chatbot.get_response(str(data['message'])) response_data = response.serialize() return jsonify({'data': response_data}) app.run(host="0.0.0.0", port=8900, debug=True)
方式二:手动处理OPTIONS请求
如果你不想依赖Flask-CORS的自动处理,也可以手动在路由里处理OPTIONS预请求:
from flask import Flask, request, jsonify app = Flask(__name__) # 路由明确包含OPTIONS方法,同时允许带/不带尾斜杠 @app.route("/chat", methods=["GET", "POST", "OPTIONS"], strict_slashes=False) def chat(): # 优先处理OPTIONS预请求 if request.method == 'OPTIONS': response = jsonify({'status': 'success'}) # 生产环境建议指定具体前端域名,不要用* response.headers.add('Access-Control-Allow-Origin', 'http://localhost:8080') response.headers.add('Access-Control-Allow-Headers', 'Content-Type') response.headers.add('Access-Control-Allow-Methods', 'GET,POST,OPTIONS') return response # 处理正常业务请求 data = request.get_json() if not data or 'message' not in data: return jsonify({'error': 'Missing message parameter'}), 400 response = chatbot.get_response(str(data['message'])) response_data = response.serialize() response = jsonify({'data': response_data}) response.headers.add('Access-Control-Allow-Origin', 'http://localhost:8080') return response app.run(host="0.0.0.0", port=8900, debug=True)
额外注意事项
- 尽量用
request.get_json()代替json.loads(request.data),它会自动校验请求的Content-Type是否为application/json,处理更安全。 - 生产环境不要使用
Access-Control-Allow-Origin: *,指定具体的前端域名能避免安全风险。 - 确保前端请求地址和路由匹配:要么前端请求
http://localhost:8900/chat,要么通过strict_slashes=False允许路由匹配带尾斜杠的地址。
内容的提问来源于stack exchange,提问作者PrestonDocks
相关产品推荐
相关产品推荐

