Fastify

    设置为 true,则会使用 Node.js 原生的 HTTP/2 模块来绑定 socket。

    • 默认值:false

    https

    用于配置服务器的 TLS socket 的对象。其选项与 Node.js 原生的 createServer 方法一致。 当值为 null 时,socket 连接将不会配置 TLS。

    当 选项设置时,https 选项也会被应用。

    • 默认值:null

    ignoreTrailingSlash

    Fastify 使用 处理路由。该选项为 true 时,尾斜杠将被省略。 这一选项应用于 server 实例上注册的所有路由。

    • 默认值:false

    maxParamLength

    你可以为通过 maxParamLength 选项为带参路由 (无论是标准的、正则匹配的,还是复数的) 设置最大参数长度。选项的默认值为 100 字符。
    当使用正则匹配的路由时,这非常有用,可以帮你抵御 。
    当达到长度限制时,将触发 not found 路由。

    bodyLimit

    定义服务器可接受的最大 payload,以字节为单位。

    • 默认值:1048576 (1MiB)

    onProtoPoisoning

    secure-json-parse 提供的功能,指定解析带有 __proto__ 键的 JSON 对象时框架的行为。 更多关于原型污染 (prototype poisoning) 的内容请看

    允许的值为 'error''remove''ignore'

    • 默认值:'error'

    onConstructorPoisoning

    由 提供的功能,指定解析带有 constructor 的 JSON 对象时框架的行为。 更多关于原型污染的内容请看 https://hueniverse.com/a-tale-of-prototype-poisoning-2610fa170061。

    允许的值为 'error''remove''ignore'

    • 默认值:'ignore'

    logger

    Fastify 依托 Pino 内建了一个日志工具。该属性用于配置日志实例。

    属性可用的值为:

    • 默认: false。禁用日志。所有记录日志的方法将会指向一个空日志工具 的实例。

    • pinoInstance: 一个已被实例化的 Pino 实例。内建的日志工具将指向这个实例。

    • object: 标准的 Pino 选项对象。 它会被直接传递进 Pino 的构造函数。如果下列属性未在该对象中定义,它们将被相应地添加:

      • genReqId: 一个同步函数,用于生成请求的标识符。默认生成按次序排列的标识符。
      • level: 最低的日志级别。若未被设置,则默认为 'info'
      • serializers: 序列化函数的哈希。默认情况下,序列化函数应用在 req (来访的请求对象)、res (发送的响应对象) 以及 err (标准的 Error 对象) 之上。当一个日志方法接收到含有上述任意属性的对象时,对应的序列化器将会作用于该属性。举例如下:

        1. fastify.get('/foo', function (req, res) {
        2. req.log.info({req}) // 日志输出经过序列化的请求对象
        3. res.send('foo')
        4. })

        用户提供的序列化函数将会覆盖对应属性默认的序列化函数。

    • loggerInstance:自定义日志工具实例。日志工具必须实现 Pino 的接口,即拥有如下方法:info, error, debug, fatal, warn, trace, child。例如:
    1. const pino = require('pino')();
    2. const customLogger = {
    3. info: function (o, ...n) {},
    4. warn: function (o, ...n) {},
    5. error: function (o, ...n) {},
    6. fatal: function (o, ...n) {},
    7. trace: function (o, ...n) {},
    8. debug: function (o, ...n) {},
    9. child: function() {
    10. const child = Object.create(this);
    11. child.pino = pino.child(...arguments);
    12. return child;
    13. },
    14. };
    15. const fastify = require('fastify')({logger: customLogger});

    默认情况下当开启日志时,Fastify 会在收到请求与发送该请求的响应时记录 info 级别的日志。你可以设置该选项为 true 来禁用该功能。这时,通过自定义 onRequestonResponse 钩子,你能更灵活地记录一个请求的开始与结束。

    • 默认值:false
    1. // 例子:通过钩子再造被禁用的请求日志功能。
    2. fastify.addHook('onRequest', (req, reply, done) => {
    3. req.log.info({ url: req.req.url, id: req.id }, 'received request')
    4. done()
    5. })
    6. fastify.addHook('onResponse', (req, reply, done) => {
    7. req.log.info({ url: req.req.originalUrl, statusCode: reply.res.statusCode }, 'request completed')
    8. done()
    9. })

    serverFactory

    通过 serverFactory 选项,你可以向 Fastify 传递一个自定义的 http server。
    serverFactory 函数的参数为 handler 函数及一个选项对象。handler 函数的参数为 requestresponse 对象,选项对象则与你传递给 Fastify 的一致。

    1. const serverFactory = (handler, opts) => {
    2. const server = http.createServer((req, res) => {
    3. handler(req, res)
    4. })
    5. return server
    6. }
    7. const fastify = Fastify({ serverFactory, modifyCoreObjects: false })
    8. fastify.get('/', (req, reply) => {
    9. reply.send({ hello: 'world' })
    10. })

    Fastify 内在地使用 Node 原生 http server 的 API。因此,如果你使用一个自定义的 server,你必须保证暴露了相同的 API。不这么做的话,你可以在 serverFactory 函数内部 return 语句之前,向 server 实例添加新的属性。
    要注意的是,我们也设置了 modifyCoreObjects: false。这是因为在诸如 Google Cloud Functions 等无服务器 (serverless) 环境下,一些 Node.js 核心的属性是不可写的。

    caseSensitive

    默认值为 true,此时路由对大小写敏感。这就意味着 /foo/Foo 是两个不同的路由。当该选项为 false 时,路由大小写不敏感,/foo/Foo 以及 /FOO 都是一样的。

    caseSensitive 设置为 false,会导致所有路径变为小写,除了路由参数与通配符。

    1. fastify.get('/user/:username', (request, reply) => {
    2. // 原 URL: /USER/NodeJS
    3. console.log(request.params.username) // -> 'NodeJS'
    4. })

    要注意的是,将该选项设为 与 相悖。

    requestIdHeader

    用来获知请求 id 的 header 名。请看 一节。

    • 默认值:'request-id'

    requestIdLogLabel

    定义日志中请求 id 的标签。

    • 默认值:'reqId'

    genReqId

    • 默认值:'request-id' header 的值 (当存在时) 或单调递增的整数 在分布式系统中,你可能会特别想覆盖如下默认的 id 生成行为。要生成 UUID,请看hyperid
    1. let i = 0
    2. const fastify = require('fastify')({
    3. genReqId: function (req) { return i++ }
    4. })

    注意:当设置了 [requestIdHeader](#requestidheader) 中定义的 header (默认为 ‘request-id’) 时,genReqId 不会 被调用。

    trustProxy

    通过开启 trustProxy 选项,Fastify 会认为使用了代理服务,且 X-Forwarded-* header 是可信的,否则该值被认为是极具欺骗性的。

    1. const fastify = Fastify({ trustProxy: true })
    • 默认值:false
    • true/false: 信任所有代理 (true) 或不信任任意的代理 (false)。
    • string: 只信任给定的 IP/CIDR (例如 '127.0.0.1')。可以是一组用英文逗号分隔的地址 (例如 '127.0.0.1,192.168.1.1/24')。
    • Array<string>: 只信任给定的 IP/CIDR 列表 (例如 ['127.0.0.1'])。
    • number: 信任来自前置代理服务器的第n跳 (hop) 地址作为客户端。
    • Function: 自定义的信任函数,第一个参数为 address

      1. function myTrustFn(address, hop) {
      2. return address === '1.2.3.4' || hop === 1
      3. }

    更多示例详见 proxy-addr

    你还可以通过 对象获取 ipipshostname 的值。

    1. fastify.get('/', (request, reply) => {
    2. console.log(request.ip)
    3. console.log(request.ips)
    4. console.log(request.hostname)
    5. })

    pluginTimeout

    单个插件允许加载的最长时间,以毫秒计。如果某个插件加载超时,则 会抛出一个含有 'ERR_AVVIO_PLUGIN_TIMEOUT' 代码的 Error 对象。

    • 默认值:10000

    Fastify 默认使用 Node.js 核心的 querystring 模块作为 query string 解析器。
    你可以通过 querystringParser 选项来使用自定义的解析器,例如 qs

    1. const qs = require('qs')
    2. const fastify = require('fastify')({
    3. querystringParser: str => qs.parse(str)
    4. })

    versioning

    默认情况下,find-my-way 使用 semver 版本号规范来为路由设置版本号。你也可以使用自定义的版本号策略。更多信息请看 的文档。

    modifyCoreObjects

    • 默认值:true

    默认情况下,Fastify 会向 Node 原生的 request 对象添加 ipipshostname 以及 log 属性 (参见 ),向原生的 response 对象添加 log 属性。你可以将 modifyCoreObjects 设为 false 来避免上述行为。

    1. const fastify = Fastify({ modifyCoreObjects: true }) // 默认值
    2. fastify.get('/', (request, reply) => {
    3. console.log(request.raw.ip)
    4. console.log(request.raw.ips)
    5. console.log(request.raw.hostname)
    6. request.raw.log('Hello')
    7. reply.res.log('World')
    8. })

    在诸如 Google Cloud Functions 等无服务器 (serverless) 环境下,禁用该选项是有用的。因为在这些环境中,ipips 并不可写。

    **请注意,我们不建议使用这些属性。它们将会在 Fastify 的下个主要版本中,与该选项一起去除。**作为替代,我们推荐使用 Fastify 的 Request 与 对象上相同的属性。

    1. const fastify = Fastify({ modifyCoreObjects: false })
    2. fastify.get('/', (request, reply) => {
    3. console.log(request.ip)
    4. console.log(request.ips)
    5. console.log(request.hostname)
    6. request.log('Hello')
    7. reply.log('World')
    8. })

    return503OnClosing

    调用 close 方法后返回 503 状态码。 如果为 false,服务器会正常处理请求。

    • 默认值:true

    ajv

    配置 Fastify 使用的 ajv 实例。这使得你无需提供一个自定义的实例。

    • 默认值:
    1. {
    2. customOptions: {
    3. removeAdditional: true,
    4. useDefaults: true,
    5. coerceTypes: true,
    6. allErrors: true,
    7. nullable: true
    8. },
    9. plugins: []
    10. }
    1. const fastify = require('fastify')({
    2. ajv: {
    3. customOptions: {
    4. nullable: false // 参见 [ajv 的配置选项](https://ajv.js.org/#options)
    5. },
    6. plugins: [
    7. require('ajv-merge-patch')
    8. [require('ajv-keywords'), 'instanceof'];
    9. // 用法: [plugin, pluginOptions] - 插件与选项
    10. // 用法: plugin - 仅插件
    11. ]
    12. }
    13. })

    http2SessionTimeout

    为每个 http2 会话设置默认。超时后,会话将关闭。默认值:5000 毫秒。

    要注意的是,使用 http2 时需要提供一个优雅的“close”体验。Node 的默认值为 0,即无超时。

    frameworkErrors

    • 默认值:null

    对于最常见的场景,Fastify 已经提供了默认的错误处理方法。这个选项允许你重写这些处理方法。

    注:目前只实现了 FST_ERR_BAD_URL 这个错误。

    1. const fastify = require('fastify')({
    2. frameworkErrors: function (error, req, res) {
    3. if (error instanceof FST_ERR_BAD_URL) {
    4. res.code(400)
    5. return res.send("Provided url is not valid")
    6. } else {
    7. res.send(err)
    8. }
    9. }
    10. })

    实例

    服务器方法

    服务器

    fastify.server:由 Fastify 的工厂函数 生成的 Node 原生 对象。

    after

    当前插件及在其中注册的所有插件加载完毕后调用。总在 fastify.ready 之前执行。

    1. fastify
    2. .register((instance, opts, done) => {
    3. console.log('当前插件')
    4. done()
    5. })
    6. .after(err => {
    7. console.log('当前插件之后')
    8. })
    9. .register((instance, opts, done) => {
    10. console.log('下一个插件')
    11. done()
    12. })
    13. .ready(err => {
    14. })

    ready

    当所有插件的加载都完成时调用。如有错误发生,它会传递一个 error 参数。

    1. fastify.ready(err => {
    2. if (err) throw err
    3. })

    调用时不加参数,它会返回一个 Promise 对象:

    1. fastify.ready().then(() => {
    2. console.log('successfully booted!')
    3. }, (err) => {
    4. })

    listen

    所有的插件加载完毕、ready 事件触发后,在指定的端口启动服务器。它的回调函数与 Node 原生方法的回调相同。默认情况下,服务器监听 localhost 所决定的地址 (127.0.0.1::1,取决于操作系统)。将地址设置为 0.0.0.0 可监听所有的 IPV4 地址。设置为 :: 则可监听所有的 IPV6 地址,在某些系统中,这么做亦可同时监听所有 IPV4 地址。监听所有的接口要格外谨慎,因为这种方式存在着固有的。

    1. fastify.listen(3000, (err, address) => {
    2. if (err) {
    3. fastify.log.error(err)
    4. process.exit(1)
    5. }
    6. })

    指定监听的地址:

    1. fastify.listen(3000, '127.0.0.1', (err, address) => {
    2. if (err) {
    3. fastify.log.error(err)
    4. process.exit(1)
    5. }
    6. })

    指定积压队列 (backlog queue size) 的大小:

    没有提供回调函数时,它会返回一个 Promise 对象:

    1. fastify.listen(3000)
    2. .then((address) => console.log(`server listening on ${address}`))
    3. .catch(err => {
    4. console.log('Error starting server:', err)
    5. process.exit(1)
    6. })
    1. fastify.listen(3000, '127.0.0.1')
    2. .then((address) => console.log(`server listening on ${address}`))
    3. .catch(err => {
    4. console.log('Error starting server:', err)
    5. process.exit(1)
    6. })

    当部署在 Docker 或其它容器上时,明智的做法是监听 0.0.0.0。因为默认情况下,这些容器并未将映射的端口暴露在 127.0.0.1

    1. fastify.listen(3000, '0.0.0.0', (err, address) => {
    2. if (err) {
    3. fastify.log.error(err)
    4. process.exit(1)
    5. }
    6. })

    假如未设置 port (或设为 0),则会自动选择一个随机可用的端口 (之后可通过 fastify.server.address().port 获知)。

    route

    将路由添加到服务器的方法,支持简写。请看。

    close

    fastify.close(callback):调用这个函数来关闭服务器实例,并触发 钩子。
    服务器会向所有新的请求发送 503 错误,并销毁它们。 要改变这一行为,请见 return503OnClosing

    如果无参调用,它会返回一个 Promise:

    1. fastify.close().then(() => {
    2. console.log('successfully closed!')
    3. }, (err) => {
    4. console.log('an error happened', err)
    5. })

    decorate*

    向 Fastify 实例、响应或请求添加装饰器函数。参阅这里了解更多。

    register

    Fastify 允许用户通过插件扩展功能。插件可以是一组路由、装饰器或其他。请看这里

    use

    向 Fastify 添加中间件,请看这里

    addHook

    向 Fastify 添加特定的生命周期钩子函数,请看这里

    prefix

    添加在路由前的完整路径。

    示例:

    1. fastify.register(function (instance, opts, done) {
    2. instance.get('/foo', function (request, reply) {
    3. // 输出:"prefix: /v1"
    4. request.log.info('prefix: %s', instance.prefix)
    5. reply.send({prefix: instance.prefix})
    6. })
    7. instance.register(function (instance, opts, done) {
    8. instance.get('/bar', function (request, reply) {
    9. // 输出:"prefix: /v1/v2"
    10. request.log.info('prefix: %s', instance.prefix)
    11. reply.send({prefix: instance.prefix})
    12. })
    13. done()
    14. }, { prefix: '/v2' })
    15. done()
    16. }, { prefix: '/v1' })

    pluginName

    当前插件的名称。有三种定义插件名称的方式(按顺序)。

    1. 如果插件使用 ,那么名称为元数据 (metadata) 中的 name
    2. 如果插件通过 module.exports 导出,使用文件名。
    3. 如果插件通过常规的 函数定义,则使用函数名。

    回退方案:插件函数的头两行将作为插件名,并使用 -- 替代换行符。这有助于在处理涉及许多插件的问题时,找到根源。

    重点:如果你要处理一些通过 包装的嵌套的异名插件,由于没有生成新的定义域,因此不会去覆盖上下文数据,而是将各插件名加入一个数组。在这种情况下,会按涉及到的插件的启动顺序,以 plugin-A -> plugin-B 的格式来展示插件名称。

    log

    日志的实例,详见。

    inject

    伪造 http 注入 (作为测试之用) 。请看。

    addSchema

    fastify.addSchema(schemaObj),向 Fastify 实例添加可共用的 schema,用于验证数据。你可以通过该 schema 的 id 在应用的任意位置使用它。
    请看一文中的范例

    setReplySerializer

    作用于未设置 Reply.serializer(func) 的所有路由的默认序列化方法。这个处理函数是完全封装的,因此,不同的插件允许有不同的错误处理函数。 注:仅当状态码为 2xx 时才被调用。关于错误处理,请看 。

    1. fastify.setReplySerializer(function (payload, statusCode){
    2. // 使用同步函数序列化 payload
    3. return `my serialized ${statusCode} content: ${payload}`
    4. })

    setSchemaCompiler

    为所有的路由设置 schema 编译器 (schema compiler),请看了解更多信息。

    setSchemaResolver

    为所有的路由设置 schema $ref 解析器 (schema $ref resolver),请看了解更多信息。

    schemaCompiler

    setSchemaCompiler 方法的简写。用于设置 schema 编译器函数,也可用于返回全部路由的 schema 编译器。

    setNotFoundHandler

    fastify.setNotFoundHandler(handler(request, reply)):为 404 状态 (not found) 设置处理函数 (handler)。向 fastify.register() 传递不同的 prefix 选项,就可以为不同的插件设置不同的处理函数。这些处理函数被视为常规的路由处理函数,因此它们的请求会经历一个完整的 。

    你也可以为 404 处理函数注册一个 preValidation 或 钩子。

    注意:通过该方法注册的 preValidation 钩子将在 Fastify 检测不到的路由中运行,即便你在路由函数中调用 reply.callNotFound 也是如此。在这种情况下,只有 preHandler 会运行。

    1. fastify.setNotFoundHandler({
    2. preValidation: (req, reply, done) => {
    3. // 你的代码
    4. done()
    5. } ,
    6. preHandler: (req, reply, done) => {
    7. // 你的代码
    8. done()
    9. }
    10. }, function (request, reply) {
    11. // 设置了 preValidation 与 preHandler 钩子的默认 not found 处理函数
    12. })
    13. fastify.register(function (instance, options, done) {
    14. instance.setNotFoundHandler(function (request, reply) {
    15. // '/v1' 开头的 URL 的 not found 处理函数,
    16. // 未设置 preValidation 与 preHandler 钩子
    17. })
    18. done()
    19. }, { prefix: '/v1' })

    setErrorHandler

    fastify.setErrorHandler(handler(error, request, reply)):设置任意时刻的错误处理函数。错误处理函数绑定在 Fastify 实例上,并且是完全封装 (fully encapsulated) 的,因此不同插件的处理函数可以不同。支持 async-await 语法。
    注:假如错误的 statusCode 小于 400,在处理错误前 Fastify 将会自动将其设为 500。

    1. fastify.setErrorHandler(function (error, request, reply) {
    2. // 记录错误
    3. this.log.error(error)
    4. // 发送错误响应
    5. reply.status(409).send({ ok: false })
    6. })
    1. var statusCode = error.statusCode
    2. if (statusCode >= 500) {
    3. log.error(error)
    4. } else if (statusCode >= 400) {
    5. log.info(error)
    6. } else {
    7. log.error(error)
    8. }

    printRoutes

    fastify.printRoutes():打印路由的基数树 (radix tree),可作调试之用。
    记得在 ready 函数的内部或之后调用它。

    1. fastify.get('/test', () => {})
    2. fastify.get('/test/hello', () => {})
    3. fastify.get('/hello/world', () => {})
    4. fastify.ready(() => {
    5. console.log(fastify.printRoutes())
    6. // └── /
    7. // ├── test (GET)
    8. // │ └── /hello (GET)
    9. // └── hello/world (GET)