Fastify

    和其他的 API 一样,addContentTypeParser 被封装在定义它的作用域中了。这就意味着如果你定义在了根作用域中,那么就是全局可用,如果你定义在一个插件中,那么它只能在那个作用域和子作用域中可用。

    Fastify 自动将解析好的 payload 添加到 Fastify request 对象,你能通过 request.body 访问。

    在使用正则匹配 content-type 解析器之前,Fastify 首先会查找解析出 string 类型值的解析器。假如提供了重复的类型,那么 Fastify 会按照提供的顺序反向查找。因此,你可以先指定一般的 content type,之后再指定更为特殊的类型,正如下面的例子一样。

    1. // 只会调用第二个解析器,因为它也匹配了第一个解析器的类型
    2. fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )
    3. fastify.addContentTypeParser('application/vnd.custom', (request, body, done) => {} )
    4. // 这才是我们期望的行为。因为 Fastify 会首先尝试匹配 `application/vnd.custom+xml` content type 解析器
    5. fastify.addContentTypeParser('application/vnd.custom', (request, body, done) => {} )
    6. fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )

    注意:早先的写法 function(req, done) 与 仍被支持,但不推荐使用。

    Body Parser

    你可以用两种方式解析消息主体。第一种方法在上面演示过了: 你可以添加定制的 content type 解析器来处理请求。第二种方法你可以在 addContentTypeParser API 传递 parseAs 参数。它可以是 'string' 或者 'buffer'。如果你使用 parseAs 选项 Fastify 会处理 stream 并且进行一些检查,比如消息主体的 最大尺寸 和消息主体的长度。如果达到了某些限制,自定义的解析器就不会被调用。

    1. try {
    2. var json = JSON.parse(body)
    3. done(null, json)
    4. } catch (err) {
    5. err.statusCode = 400
    6. done(err, undefined)
    7. }
    8. })

    查看例子 。

    自定义解析器的选项
    • parseAs (string): 'string' 或者 定义了如何收集进来的数据。默认是 'buffer'
    • bodyLimit (number): 自定义解析器能够接收的最大的数据长度,比特为单位。默认是全局的消息主体的长度限制。

    捕获所有

    在这种情况下,所有的没有特定 content type 解析器的请求都会被这个方法处理。

    对请求流 (stream) 执行管道输送 (pipe) 操作也是有用的。你可以如下定义一个 content 解析器:

    1. fastify.addContentTypeParser('*', function (request, payload, done) {
    2. done()

    之后通过核心 HTTP request 对象将请求流直接输送到任意位置:

    1. const split2 = require('split2')
    2. const pump = require('pump')
    3. fastify.addContentTypeParser('*', (request, payload, done) => {
    4. done(null, pump(payload, split2(JSON.parse)))
    5. })
    6. fastify.route({
    7. method: 'POST',
    8. url: '/api/log/jsons',
    9. handler: (req, res) => {
    10. req.body.on('data', d => console.log(d)) // 记录每个来访的对象
    11. })

    关于输送上传的文件,请看。