Axios Post请求返回400 Bad Request问题排查(React/Redux Toolkit/TS)
createAsyncThunk发起Axios POST请求返回400 Bad Request排查方案
400错误核心是服务端无法正确解析/处理客户端发送的请求,结合贴出的代码,按优先级排查以下问题:
核心问题点
- 后端未配置JSON请求体解析中间件
当前后端代码没有配置express.json()(Express 4.16+内置)或body-parser中间件,POST请求携带的JSON格式请求体不会被解析,req.body会是undefined,此时访问req.body.data会直接抛异常返回400错误,这也是Postman发JSON请求同样报400的最常见原因。 - 请求缺少鉴权信息
/createList路由绑定了requireSignin鉴权中间件,但前端Axios请求、Postman测试时都没有携带Authorization请求头(登录后拿到的有效token),会直接被鉴权中间件拦截返回4xx错误。 - CORS配置位置与规则错误
现有代码把CORS响应头写在了路由处理函数内部,请求如果被鉴权中间件拦截,根本走不到添加CORS头的逻辑;同时Access-Control-Allow-Headers只配置了authorization,缺少Content-Type,会导致浏览器发application/json请求时的OPTIONS预检直接失败。 - 代码逻辑瑕疵(虽不直接触发400但会导致异常)
- Axios请求没有加
await关键字,try/catch无法捕获异步请求错误 - 后端
User.updateOne是异步操作,没有等待执行完成就提前返回响应,可能出现前端提示成功但数据库未更新的问题 - 后端没有做参数判空,出错时无法返回明确的错误提示
- Axios请求没有加
修复步骤
1. 补全后端全局基础配置
在Express实例初始化后、所有路由注册前,添加以下配置:
// 解析JSON请求体 app.use(express.json()) // 全局CORS配置,不要写在单个路由处理函数里 app.use((req, res, next) => { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT"); // 补充允许Content-Type头 res.header("Access-Control-Allow-Headers", "Authorization, Content-Type"); // 直接放行OPTIONS预检请求 if (req.method === "OPTIONS") return res.sendStatus(200); next(); }) // 之后再注册/signup、/createList等业务路由
2. 修正前端createAsyncThunk请求逻辑
补全鉴权头,修正异步写法:
export const createNewList = createAsyncThunk("myLists/createNewList", async (listData: listObject) => { try{ // 从本地存储取登录时保存的鉴权token,键名和本地存储时保持一致 const token = localStorage.getItem("authToken"); const response = await axios.post( "http://localhost:3020/createList", { data: listData }, { headers: { // token格式和requireSignin中间件解析逻辑保持一致,一般为Bearer前缀 "Authorization": `Bearer ${token}`, "Content-Type": "application/json" } } ) // 记得抛出错误,否则createAsyncThunk无法触发rejected状态 return response.data; } catch(error: any){ console.log("请求错误:", error.response?.status, error.response?.data); throw error; } })
3. 修正后端createList路由逻辑
增加参数校验,等待异步数据库操作完成再返回响应:
exports.createList = async function(req, res, next){ try { // 参数判空,缺参时明确返回400 if (!req.body?.data?.listMakerID) { return res.status(400).send({ error: "缺少必要的书单参数" }); } const data = req.body.data; const userID = data.listMakerID; // 等待数据库操作完成再返回 await User.updateOne({ uniqueID: userID }, { $push: { lists: data } }); res.send("successful"); } catch (err) { console.log("创建书单错误:", err); res.status(500).send({ error: "服务端处理失败" }); } }
验证顺序
- 先用Postman测试:请求体选
raw -> JSON,传入完整的{"data": {对应listData结构对象}},请求头添加合法的Authorization值(从登录接口返回结果中获取),先测通Postman再调试前端 - 如果Postman不带token返回400/401,就是鉴权中间件拦截,必须传入有效token才能通过
- 如果带了token还是400,查看后端控制台报错,如果出现
Cannot read property 'data' of undefined,说明JSON解析中间件没有配置生效
内容的提问来源于stack exchange,提问作者Iggee Xy
相关产品推荐
相关产品推荐

