Flask接口在Node.js Fetch请求正常,Chrome中报400错误排查
问题
为何以下JavaScript代码在Node.js中可正常运行,但在Chrome中无法正常请求Flask接口?
补充说明:
- 使用curl命令
curl -X POST -H "Content-Type: application/json" -d '{"prompt":"testprompt"}' 192.168.122.234:3000/test请求可成功。 - Chrome中的错误与跨域无关,错误信息为:
VM10:4 POST http://192.168.122.234:3000/test net::ERR_ABORTED 400 (BAD REQUEST)
涉及代码
Flask后端代码(flasktest.py)
from flask import Flask, jsonify, request, render_template app = Flask(__name__) @app.route('/test', methods=('GET', 'POST',)) def testfn(): # GET request if request.method == 'GET': message = {'greeting':'Hello from Flask!'} return jsonify(message) # serialize and use JSON headers # POST request if request.method == 'POST': print(request.get_json()) # parse as JSON return 'Sucesss', 200
前端JavaScript代码
// Example POST method implementation: async function postData(url = '', data = {}) { // Default options are marked with * const response = await fetch(url, { method: 'POST', // *GET, POST, PUT, DELETE, etc. mode: 'no-cors', // no-cors, *cors, same-origin cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached credentials: 'same-origin', // include, *same-origin, omit headers: { 'Content-Type': 'application/json' // 'Content-Type': 'application/x-www-form-urlencoded', }, redirect: 'follow', // manual, *follow, error referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin,> body: JSON.stringify(data) // body data type must match "Content-Type" header }); return response; // response.json() ??? parses JSON response into native JavaScript objects } postData('http://192.168.122.234:3000/test', {prompt: "hello" }) .then((data) => { console.log(data); // JSON data parsed by `data.json()` call });
核心原因
- 浏览器
no-cors模式的限制
当前端fetch设置mode: 'no-cors'时,浏览器会强制屏蔽自定义请求头,原本设置的Content-Type: application/json会被替换为text/plain。而Flask的request.get_json()默认只解析Content-Type为application/json的请求体,无法识别text/plain类型的内容,因此返回400错误。
Node.js和curl不受浏览器同源策略限制,no-cors规则不生效,所以能正常发送符合要求的请求。
- Flask代码的缩进错误
原代码中return 'Sucesss', 200语句缩进错误,位于testfn函数外部,这会导致代码运行报错。结合你描述的Node.js和curl请求成功的情况,推测这是输入时的格式失误,实际运行的代码中该语句应该在函数内部。
解决方案
1. 调整前端fetch配置(优先方案)
移除mode: 'no-cors',使用默认的cors模式,同时确保Flask后端配置CORS支持以避免跨域问题:
修改后的前端代码:
async function postData(url = '', data = {}) { const response = await fetch(url, { method: 'POST', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, redirect: 'follow', referrerPolicy: 'no-referrer', body: JSON.stringify(data) }); return response.json(); // 解析JSON返回值,便于后续处理 } postData('http://192.168.122.234:3000/test', {prompt: "hello" }) .then((data) => { console.log(data); });
2. 修复Flask代码并配置CORS
修正缩进错误,同时引入flask-cors库开启跨域支持,优化请求解析逻辑:
from flask import Flask, jsonify, request from flask_cors import CORS # 引入CORS支持 app = Flask(__name__) CORS(app) # 全局开启跨域支持 @app.route('/test', methods=('GET', 'POST',)) def testfn(): if request.method == 'GET': message = {'greeting':'Hello from Flask!'} return jsonify(message) if request.method == 'POST': req_data = request.get_json() # 处理JSON解析失败的情况 if not req_data: return jsonify({"error": "无效的JSON数据"}), 400 print(req_data) return jsonify({"status": "Success"}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000, debug=True)
3. 可选:兼容no-cors模式(不推荐)
如果因特殊限制必须使用no-cors,可修改Flask后端,让它能解析text/plain类型的请求体:
# 在POST处理逻辑中修改 if request.method == 'POST': import json try: req_data = json.loads(request.data.decode('utf-8')) print(req_data) return jsonify({"status": "Success"}), 200 except json.JSONDecodeError: return jsonify({"error": "数据解析失败"}), 400
内容的提问来源于stack exchange,提问作者Gediz GÜRSU
相关产品推荐
相关产品推荐

