restify 请求体处理:req.body 为什么总收不到
服务启动一切正常,curl 打过去返回 200,可处理器里 req.body 始终是 undefined;又或者文件上传的页面不报错,req.files 里却什么都没有。这两类问题都出在 restify 请求体处理上——它不会替你解析请求体,得显式挂插件。jsonBodyParser 负责 JSON,multipartBodyParser 负责文件上传,挂对之后处理器里拿到的才是现成对象。
一条请求的三站旅程
请求打到你的服务器,会按顺序经过三站。第一站是 bodyReader,它把 TCP 连接里的原始字节流读出来,装进 req.body(字符串或 Buffer)。第二站是你挂的解析器,各自看一眼 Content-Type(一个告诉服务器"数据长什么样"的请求头),对得上才接手,jsonBodyParser 只认 application/json。第三站是你的路由处理器,这时候 req.body 已经是一个可以直接用的 JavaScript 对象。
三个场景
JSON 收数据:怎么挂载 jsonBodyParser
最小配置就下面这一段:
var restify = require('restify');
var server = restify.createServer();
server.use(restify.plugins.jsonBodyParser());
server.post('/api/orders', function (req, res, next) {
res.send(req.body);
});
有两个容易栽的点。一是 req.rawBody:解析前原文会留在这上面,做日志、审计、二次处理都用得上,别当没用直接丢。二是 JSON 写坏了会抛 InvalidContentError(400),报错信息里带着具体解析原因,客户端好定位问题。
收表单:怎么防止数组参数被静默丢掉
urlEncodedBodyParser 处理 application/x-www-form-urlencoded,底层是 qs 库。像 a[0]=x&a[1]=y 这种数组参数,下标一旦超过 arrayLimit(默认 20),超出的部分会被悄悄丢掉。
生产环境务必开
throwOnLimitExceeded: true,把行为从"静默丢弃"改成抛InvalidContentError(400),客户端才能知道数据超限了。
不丢还好,一丢就是客户端不报错、服务端不记日志、数据无声无息地没了,排查起来最费劲。参数细节见 lib/plugins/formBodyParser.js。
收文件:怎么设 uploadDir 和大小上限
multipartBodyParser 基于 formidable,结果拆成两处:表单字段(普通 key/value)进 req.body,上传文件对象(路径、大小、类型等)进 req.files。uploadDir 必须指一个可写目录,formidable 才知道把临时文件落到哪。大小上限有两个参数:maxFileSize 管单个文件,maxFieldsSize 管表单字段。mapFiles: true 会把文件内容直接读进 req.params,适合小文件场景;大文件建议只落在 req.files,别硬读进内存。
安全红线与错误码 ⚠️
maxBodySize 是通用参数,能透传给任意解析器,bodyReader 拿它把体积关,默认 2MB,超了抛 PayloadTooLargeError。比如 jsonBodyParser({ maxBodySize: 1024 * 1024 })。常见错误码三个:
| 错误 | 状态码 | 什么时候抛 |
|---|---|---|
PayloadTooLargeError | 413 | 请求体超过 maxBodySize |
InvalidContentError | 400 | JSON / 表单解析失败,或超限且开了 throwOnLimitExceeded |
UnsupportedMediaTypeError | 415 | Content-Encoding 不是 gzip |
body 收不到时按什么顺序查
倒着查最快:
- 挂载顺序:解析器是不是挂在依赖
req.body的中间件之前?挂晚了,处理器执行时 body 自然是空的。 - Content-Type 是否匹配:发的是
application/json却只挂了表单解析器,解析器直接跳过,req.body还是原文。 - 是否撞上 maxBodySize:大文件超过 2MB,先被
bodyReader拦下,返回 413。
记住一句话:请求体永远不会被自动解析,插件不挂,body 就是空的。各参数细节见 docs/_api/plugins.md。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



