共计 3248 个字符,预计需要花费 9 分钟才能阅读完成。
在开发中我们会遇到这样的问题:前端使用 ajax 正常发起 POST 请求,把数据都塞在 body 里,然后在使用 NodeJs 做服务端接受请求时,发现拿不到 `request.body` 的内容,这是怎么回事呢?
浏览器在发起 POST 请求时,我们一般会指定头部:Content-Type
,最常见的就是application/json
,代表传输的是 json 数据,对应的,我们在 NodeJs 服务端需要去解析这些数据。
解析 body 最常用的库是body-parser
,它支持对多种类型进行解析:
解析 JSON
发出请求需要带上Content-Type:application/json
。
服务端设置:
app.use(bodyParser.json(options))
options是一个包含以下可选值的对象
- inflate – 设置为 true 时,deflate 压缩数据会被解压缩;设置为 true 时,deflate 压缩数据会被拒绝。默认为 true。
- limit – 设置请求的最大数据量。默认为 ’100kb’
- reviver – 传递给 JSON.parse()方法的第二个参数,详见JSON.parse()
- strict – 设置为 true 时,仅会解析 Array 和 Object 两种格式;设置为 false 会解析所有 JSON.parse 支持的格式。默认为 true
- type – 该选项用于设置为指定 MIME 类型的数据使用当前解析中间件。这个选项可以是一个函数或是字符串,当是字符串是会使用 type-is 来查找 MIMI 类型;当为函数时,中间件会通过 fn(req)来获取实际值。默认为
application/json
。 - verify – 这个选项仅在 verify(req, res, buf, encoding)时受支持
解析二进制
发出请求可以带上自定义 type,方便服务端处理,例如Content-Type:application/x-gzip
。
服务端设置:
app.use(bodyParser.raw(options))
bodyParser.raw
返回一个仅处理字符串格式处理的中间件。这个方法支持 gzip
和deflate
编码的数据压缩。解析后,其后的所有的 req.body
中将会是一个字符串值。
options是一个包含以下可选值的对象
- defaultCharset – 如果 Content-Type 后没有指定编码时,使用此编码。默认为 ’utf-8′
- inflate – 设置为 true 时,deflate 压缩数据会被解压缩;设置为 true 时,deflate 压缩数据会被拒绝。默认为 true。
- limit – 设置请求的最大数据量。默认为 ’100kb’
- type – 该选项用于设置为指定 MIME 类型的数据使用当前解析中间件。这个选项可以是一个函数或是字符串,当是字符串是会使用 type-is 来查找 MIMI 类型;当为函数是,中间件会通过 fn(req)来获取实际值。默认为
application/octet-stream
。也就是说这里可以指定我们自定义的一些Content-Type
,来告诉服务端需要对哪些请求进行解析。 - verify – 这个选项仅在 verify(req, res, buf, encoding)时受支持
解析文本
发出请求带有 typeContent-Type:text/plain
。
服务端设置:
app.use(bodyParser.text(options))
将所有的实体解析为字符串,只查看内容类型头与类型选项匹配的请求。该解析器支持 gzip 的自动解压缩和压缩编码。
在中间件 (即 req.body) 之后,在请求对象上填充包含解析数据的新体字符串。这将是一个主体的字符串。
options是一个包含以下可选值的对象
- defaultCharset – 如果 Content-Type 在请求的标题中未指定字符集,请指定文本内容的缺省字符集。默认为 utf-8。
- inflate – 设置为 true 时,deflate 压缩数据会被解压缩;设置为 true 时,deflate 压缩数据会被拒绝。默认为 true。
- limit – 控制最大请求主体大小。如果这是一个数字,则该值指定字节数; 如果它是一个字符串,则将该值传递给 字节库进行解析。默认为’100kb’。
- type – 该 type 选项用于确定中间件将解析的 MIME 类型。该选项可以是字符串,字符串数组或函数。如果不是函数,则 type 选项直接传递到 类型库,这可以是扩展名(like txt),MIME 类型(like text/pl ain)或带有通配符(如 /or text/*)的 MIME 类型。如果一个函数,这个 type 选项被调用,fn(req)并且如果返回一个真值,那么请求被解析。默认为 text/plain。
- verify – 该 verify 选项(如果提供)被称为 verify(req, res, buf,encoding),其中 buf 是 Buffer 原始请求主体,并且 encoding 是请求的编码。抛出错误可以中止解析。
特别说明
使用 navigation.sendBeacon
发出请求时,默认传的Content-Type:text/plain
, 所以解析该类请求需要用bodyParser.text()
。
解析 urlencode
发出请求带有 type:Content-Type:application/x-www-form-urlencoded
。
服务端设置:
app.use(bodyParser.urlencoded(options))
返回仅解析 urlencoded 正文的中间件,只查看 Content-Type 头部与 type 选项匹配的请求。此解析器只接受身体的 UTF- 8 编码,并支持自动 gzip 和 deflate 编码。
body 包含解析数据的新对象 request 在中间件(iereq.body)之后被填充在对象上。该对象将包含键 - 值对,其中该值可以是一个字符串或阵列(时 extended 是 false),或任何类型的(当 extended 是 true)。
options是一个包含以下可选值的对象
- extended – 该 extended 选项允许选择是将 URL 编码的数据与 querystring 库(当值为 false)或 qs 库(当值为 true)解析。“extended”语法允许将丰富的对象和数组编码为 URL 编码的格式,从而允许使用 URL 编码的类似 JSON 的体验。有关更多信息,请 参阅qs 库。
- limit – 设置为 true 时,deflate 压缩数据会被解压缩;设置为 true 时,deflate 压缩数据会被拒绝。默认为 true。limit 控制最大请求主体大小。如果这是一个数字,则该值指定字节数; 如果它是一个字符串,则将该值传递给 字节库进行解析。默认为’100kb’。
- parameterLimit – 该 parameterLimit 选项控制 URL 编码数据中允许的最大参数数量。如果一个请求包含比这个值更多的参数,一个 413 将被返回给客户端。默认为 1000。
- type – 该 type 选项用于确定中间件将解析的 MIME 类型。该选项可以是字符串,字符串数组或函数。如果不是函数,则 type 选项直接传递到类型库,这可以是扩展名(例如 urlencoded),MIME 类型(例如 application/x-www-form-urlencoded)或带有通配符(如 */x-www-form-urlencoded)的 MIME 类型。如果一个函数,这个 type 选项被调用,fn(req)并且如果返回一个真值,那么请求被解析。默认为
application/x-www-form-urlencoded
。 - verify – 该 verify 选项(如果提供)被称为 verify(req,res,buf,encoding),其中 buf 是 Buffer 原始请求主体,并且 encoding 是请求的编码。抛出错误可以中止解析。
总结
在实际开发过程中,我们需要知道浏览器或者说客户端请求的头部:Content-Type 是什么,然后在服务端根据对应的 type 去进行数据解析,这样才能正确拿到数据。