Flask-RESTful接口接收JavaScript POST请求时body为空如何解决
问题根源
核心错误是前后端传递的请求体格式不匹配:
- 前端JS代码明确设置了
Content-Type: application/json,发送的是JSON序列化后的字符串格式请求体 - 后端Flask代码使用
flask.request.form.to_dict()取参数,这个方法仅支持解析application/x-www-form-urlencoded、multipart/form-data格式的表单请求,完全不会解析JSON格式的请求体,所以拿到的是空字典。
解决方案
选择任意一端适配格式即可,推荐两种可行方案:
方案1:后端适配JSON请求(推荐,符合前后端分离接口规范)
修改Flask的post方法里取参数的逻辑,把request.form换成request.get_json(),同时补充参数校验避免报错:
class Login(Resource): def post(self): # 替换原有的request.form.to_dict() data = flask.request.get_json() # 补充参数存在性校验 if not data or 'email' not in data or 'passw_hashed' not in data: return {"error": "缺少必要参数"}, 400 lst = conn.execute(f"""SELECT AccountID, Role FROM Account WHERE Email = \"{data['email']}\" AND PassW = \"{data['passw_hashed']}\" """).fetchall() return {"LoginSucces": [{"AccountId": e[0], "Role": e[1]} for e in lst]}
方案2:前端适配表单格式请求
修改JS代码,不发送JSON,改为发送FormData格式的请求,同时删除Content-Type: application/json的请求头设置:
function req_login(){ let email_p = document.getElementById("login_email").value let passw = document.getElementById("login_passw").value // 替换原来的JSON序列化逻辑,构造FormData对象 let data = new FormData(); data.append('email', email_p); data.append('passw_hashed', passw.hashCode()); const request = new XMLHttpRequest(); request.open("POST", IP+"/login"); request.setRequestHeader("Accept", "application/json"); // 删掉设置Content-Type为json的代码,FormData会自动设置正确的请求头 request.send(data); request.onload = (e) => { let jsret = JSON.parse(request.response); let topkey = Object.keys(jsret); let data_arr = jsret[topkey]; alert(data_arr['AccountId']); } }
额外注意事项
- 你当前的SQL查询是直接字符串拼接,存在严重的SQL注入风险,必须改为参数化查询,修改示例:
# 不要直接拼接字符串,用?做占位符,参数放在execute的第二个参数里 lst = conn.execute("SELECT AccountID, Role FROM Account WHERE Email = ? AND PassW = ?", (data['email'], data['passw_hashed'])).fetchall()
- 你手动构造JSON字符串的测试代码不符合JSON规范,JSON要求所有key必须用双引号包裹,正确写法是
const data = '{"email": "tst@gmail.com", "passw_hashed": "testtest123"}',日常使用推荐优先调用JSON.stringify自动序列化,避免手动写格式错误。
内容的提问来源于stack exchange,提问作者FoxSrk
相关产品推荐
相关产品推荐

