Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
229 lines (189 sloc) 8 KB

Fastify

回复

处理器函数的第二个参数为 Reply。 Reply 是 Fastify 的一个核心对象。它暴露了以下函数:

  • .code(statusCode) - 设置状态码。
  • .status(statusCode) - .code(statusCode) 的别名。
  • .header(name, value) - 设置响应 header。
  • .getHeader(name) - 获取某个 header 的值。
  • .hasHeader(name) - 检查某个 header 是否设置。
  • .type(value) - 设置 Content-Type header。
  • .redirect([code,] url) - 重定向至指定的 url,状态码可选 (默认为 302)。
  • .serialize(payload) - 使用默认的 json 序列化工具序列化指定的 payload,并返回处理后的结果。
  • .serializer(function) - 设置自定义的 payload 序列化工具。
  • .send(payload) - 向用户发送 payload。类型可以是纯文本、buffer、JSON、stream,或一个 Error 对象。
  • .sent - 一个 boolean,检查 send 是否已被调用。
  • .res - Node 原生的 http.ServerResponse 对象。
fastify.get('/', options, function (request, reply) {
  // 你的代码
  reply
    .code(200)
    .header('Content-Type', 'application/json; charset=utf-8')
    .send({ hello: 'world' })
})

另外,Reply 能够访问请求的上下文:

fastify.get('/', {config: {foo: 'bar'}}, function (request, reply) {
  reply.send('handler config.foo = ' + reply.context.config.foo)
})

.code(statusCode)

如果没有设置 reply.codestatusCode 会是 200

.header(key, value)

设置响应 header。如果值被省略或为 undefined,将被强制设成 ''

更多信息,请看 http.ServerResponse#setHeader

.getHeader(key)

获取已设置的 header 的值。

reply.header('x-foo', 'foo')
reply.getHeader('x-foo') // 'foo'

.removeHeader(key)

清除已设置的 header 的值。

reply.header('x-foo', 'foo')
reply.removeHeader('x-foo')
reply.getHeader('x-foo') // undefined

.hasHeader(key)

返回一个 boolean,用于检查是否设置了某个 header。

.redirect(dest)

重定向请求至指定的 url,状态码可选,当未通过 code 方法设置时,默认为 302

reply.redirect('/home')

.type(contentType, type)

设置响应的 content type。 这是 reply.header('Content-Type', 'the/type') 的简写。

reply.type('text/html')

.serializer(func)

.send() 方法会默认将 BufferstreamstringundefinedError 之外类型的值 JSON-序列化。假如你需要在特定的请求上使用自定义的序列化工具,你可以通过 .serializer() 来实现。要注意的是,如果使用了自定义的序列化工具,你必须同时设置 'Content-Type' header。

reply
  .header('Content-Type', 'application/x-protobuf')
  .serializer(protoBuf.serialize)

注意,你并不需要在一个 handler 内部使用这一工具,因为 Buffers、streams 以及字符串 (除非已经设置了序列化工具) 被认为是已序列化过的。

reply
  .header('Content-Type', 'application/x-protobuf')
  .send(protoBuf.serialize(data))

请看 .send() 了解更多关于发送不同类型值的信息。

.send(data)

顾名思义,.send() 是向用户发送 payload 的函数。

对象

如上文所述,如果你发送 JSON 对象时,设置了输出的 schema,那么 send 会使用 fast-json-stringify 来序列化对象。否则,将使用 JSON.stringify()

fastify.get('/json', options, function (request, reply) {
  reply.send({ hello: 'world' })
})

字符串

在未设置 Content-Type 的时候,字符串会以 text/plain; charset=utf-8 类型发送。如果设置了 Content-Type,且使用自定义序列化工具,那么 send 发出的字符串会被序列化。否则,字符串不会有任何改动 (除非 Content-Type 的值为 application/json; charset=utf-8,这时,字符串会像对象一样被 JSON-序列化,正如上一节所述)。

fastify.get('/json', options, function (request, reply) {
  reply.send('plain string')
})

Streams

send 开箱即用地支持 stream。它使用 pump 来避免文件描述符 (file descriptors) 的泄露。如果在未设置 'Content-Type' header 的情况下发送 stream,它会被设定为 'application/octet-stream'

fastify.get('/streams', function (request, reply) {
  const fs = require('fs')
  const stream = fs.createReadStream('some-file', 'utf8')
  reply.send(stream)
})

Buffers

未设置 'Content-Type' header 的情况下发送 buffer,send 会将其设置为 'application/octet-stream'

const fs = require('fs')
fastify.get('/streams', function (request, reply) {
  fs.readFile('some-file', (err, fileBuffer) => {
    reply.send(err || fileBuffer)
  })
})

Errors

若使用 send 发送一个 Error 的实例,Fastify 会自动创建一个如下的错误结构:

{
  error: String        // http 错误信息
  message: String      // 用户错误信息
  statusCode: Number   // http 状态码
}

你可以向 Error 对象添加自定义属性,例如 codeheaders,这可以用来增强 http 响应。
注意:如果 send 一个错误,但状态码小于 400,Fastify 会自动将其设为 500。

贴士:你可以通过 http-errors 来简化生成的错误:

fastify.get('/', function (request, reply) {
  reply.send(httpErrors.Gone())
})

如果你想完全自定义错误响应,请看 setErrorHandler API。

statusstatusCode 属性为 404 的错误,会被导引到 not found 的处理函数。 更多信息,详见 server.setNotFoundHandler API:

fastify.setNotFoundHandler(function (request, reply) {
  reply.type('text/plain').send('a custom not found')
})

fastify.get('/', function (request, reply) {
  reply.send(new httpErrors.NotFound())
})

最终 payload 的类型

发送的 payload (序列化之后、经过任意的 onSend 钩子) 必须为下列类型之一,否则将会抛出一个错误:

  • string
  • Buffer
  • stream
  • undefined
  • null

Async-Await 与 Promise

Fastify 原生地处理 promise 并支持 async-await。
请注意,在下面的例子中我们没有使用 reply.send。

fastify.get('/promises', options, function (request, reply) {
  return new Promise(function (resolve) {
    setTimeout(resolve, 200, { hello: 'world' })
  })
})

fastify.get('/async-await', options, async function (request, reply) {
  var res = await new Promise(function (resolve) {
    setTimeout(resolve, 200, { hello: 'world' })
  })
  return res
})

被 reject 的 promise 默认发送 500 状态码。要修改回复,可以 reject 一个 promise,或在 async 函数 中进行 throw 操作,同时附带上一个有 statusCode (或 status) 与 message 属性的对象。

fastify.get('/teapot', async function (request, reply) => {
  const err = new Error()
  err.statusCode = 418
  err.message = 'short and stout'
  throw err
})

想要了解更多?请看 Routes#async-await