TypeScript Express使用内置解析器时req.body为undefined如何解决?
问题现象
开发TypeScript API时,使用Express内置的默认解析器获取请求体时,得到的req.body值为undefined。使用已废弃的body-parser库作为POST路由中间件可以得到预期结果,需要找合规的替代方案。
初始错误代码
入口代码
import express from 'express'; import { router } from './routes'; const app = express(); const port = 3000; app.use(router); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.listen(port, () => { console.log(`App rodando na porta: ${port}`); });
路由代码
// import bodyParser from 'body-parser'; import express from 'express'; import { createUserService } from '../service'; export const router = express.Router(); router.post('/users', async (req, res) => { try { const { name, email, password } = req.body; await createUserService({ name, email, password }); res.status(201).send({ name, email, password }).status(201); } catch (error) { res.status(400).send({ error: error.message }); } });
问题原因
Express中间件的执行顺序和注册顺序完全一致,初始代码中将请求体解析中间件注册在了路由之后,请求到达时会先进入路由处理逻辑,此时解析中间件还未执行,所以req.body为undefined。
无需使用废弃的body-parser,Express v4.16.0之后已经内置了express.json()和express.urlencoded()两个解析中间件,功能和body-parser完全一致。
解决方案
两种注册方式二选一即可:
方案1:调整全局中间件注册顺序,将解析中间件放在路由之前
修改入口代码如下:
import express from 'express'; import { router } from './routes'; const app = express(); const port = 3000; // 先注册解析中间件 app.use(express.json()); app.use(express.urlencoded({ extended: true })); // 再注册路由 app.use(router); app.listen(port, () => { console.log(`App rodando na porta: ${port}`); });
方案2:在路由内部单独注册解析中间件
适合仅需要给部分路由开启请求体解析的场景:
路由代码
import express from 'express'; import { createUserService } from '../service'; const router = express.Router(); // 路由内注册解析中间件 router.use(express.json()); router.use(express.urlencoded({ extended: true })); router.post('/users', async (req, res) => { try { const { name, email, password } = req.body; await createUserService({ name, email, password }); res.status(201).send({ name, email, password }).status(201); } catch (error) { res.status(400).send({ error: error.message }); } }); export { router };
入口代码
import express from 'express'; import { router } from './routes'; const app = express(); const port = 3000; app.use(router); app.listen(port, () => { console.log(`App rodando na porta: ${port}`); });
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

