You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

6.1 KiB

更新比较慢的版本,先熟悉这个教程和这个框架
fastify/docs-chinese: Fastify 中文文档 (github.com)

开始

准备

npm init -y
# 运行处加入 "build": "tsc -p tsconfig.json",
npx tsc --init
pnpm i -S fastify
pnpm i -D typescript @types/node
// started.ts
import Fastify from 'fastify'  
  
const fastify = Fastify({  
    logger: false  
})  
  
fastify.get('/', async (request, reply) => {  
    return "Hello World"  
})  
  
async function start(){  
    try{  
        await fastify.listen({  
            port:3000,  
            host:'0.0.0.0'  
        })  
    }catch (e){  
        fastify.log.error(e)  
    }  
}  
  
start()

运行

npm run build
node started.js

路由

完整格式

fastify.route({
  method: 'GET',// 请求类型
  url: '/',// 请求地址
  schema: {// 请求参数验证
    querystring: {
      name: { type: 'string' },
      excitement: { type: 'integer' }
    },
    response: {// 响应参数验证
      200: {
        type: 'object',
        properties: {
          hello: { type: 'string' }
        }
      }
    }
  },
  handler: function (request, reply) {// 响应程序
    reply.send({ hello: 'world' })
  }
})

简写格式

  • 也可以将处理函数卸载opts里面,但是如果简写中和opts里面都写了处理函数会报错
const opts = {
  schema: {
    response: {
      200: {
        type: 'object',
        properties: {
          hello: { type: 'string' }
        }
      }
    }
  }
}
fastify.get('/', opts, (request, reply) => {
  reply.send({ hello: 'world' })
})

URL构建

  • Fastify 同时支持静态与动态的 URL
  • 要注册一个参数命名的路径,请在参数名前加上_冒号_。_星号_表示通配符 注意,静态路由总是在参数路由和通配符之前进行匹配
// 参数路由
fastify.get('/example/:userId', (request, reply) => {})
fastify.get('/example/:userId/:secretToken', (request, reply) => {})

// 通配符
fastify.get('/example/*', (request, reply) => {})
// 多参数
fastify.get('/example/near/:lat-:lng/radius/:r', (request, reply) => {})
// 真实的冒号:
fastify.post('/name::verb') // 将被解释为 /name:verb

Async, Await

  • 可以直接使用return返回值
  • 假如在路由中,reply.send() 脱离了 promise 链,在一个基于回调的 API 中被调用,你可以使用 await reply, 也可以是return reply
    •  return value  reply.send(value)同时使用只会发送第一次,同时还会触发警告日志,因为你试图发送两次响应。
fastify.get('/', options, async function (request, reply) {
  setImmediate(() => {
    reply.send({ hello: 'world' })
  })
  await reply
  // return reply
})

路由前缀

// server.js
const fastify = require('fastify')()

fastify.register(require('./routes/v1/users'), { prefix: '/v1' })
fastify.register(require('./routes/v2/users'), { prefix: '/v2' })

fastify.listen(3000)
// routes/v1/users.js
module.exports = function (fastify, opts, done) {
  fastify.get('/user', handler_v1)
  done()
}
// routes/v2/users.js
module.exports = function (fastify, opts, done) {
  fastify.get('/user', handler_v2)
  done()
}

自定义日志级别

  • 可以在统一路由加入打印固定字段的,但是非必要
// server.js
const fastify = require('fastify')({ logger: true })

fastify.register(require('./routes/user'), { logLevel: 'warn' })
fastify.register(require('./routes/events'), { logLevel: 'debug' })

fastify.listen(3000)
  • 也可以直接在路由的opts中定义
fastify.get('/', { logLevel: 'warn' }, (request, reply) => {
  reply.send({ hello: 'world' })
})

装饰器

fastify.decorate('utility', function () {
  // 新功能的代码
})
fastify.decorate('conf', {
  db: 'some.db',
  port: 3000
})
// 通过装饰属性的名称便可访问值:
fastify.utility()
console.log(fastify.conf.db)

路由函数的 this 指向 Fastify server

fastify.decorate('db', new DbConnection())

fastify.get('/', async function (request, reply) {
  reply({hello: await this.db.query('world')})
})

检查装饰器的存在

用于检查服务器实例上是否存在某个装饰器:

// 用于检查服务器实例上是否存在某个装饰器:
fastify.hasDecorator('utility')
// 用于检查 Request 实例上是否存在某个装饰器
fastify.hasRequestDecorator('utility')
// 用于检查 Reply 实例上是否存在某个装饰器
fastify.hasReplyDecorator('utility')

验证和序列化

验证器复用

  • myField: { $ref: '#foo'} 将在当前 schema 内搜索 $id: '#foo' 字段。
  • myField: { $ref: '#/definitions/foo'} 将在当前 schema 内搜索 definitions.foo 字段。
  • myField: { $ref: 'http://url.com/sh.json#'} 会搜索含 $id: 'http://url.com/sh.json' 的共用 schema。
  • myField: { $ref: 'http://url.com/sh.json#/definitions/foo'} 会搜索含 $id: 'http://url.com/sh.json' 的共用 schema,并使用其 definitions.foo 字段。
  • myField: { $ref: 'http://url.com/sh.json#foo'} 会搜索含 $id: 'http://url.com/sh.json' 的共用 schema,并使用其内部带 $id: '#foo' 的对象。
fastify.addSchema({
  $id: 'http://example.com/',
  type: 'object',
  properties: {
    hello: { type: 'string' }
  }
})

fastify.post('/', {
  handler () {},
  schema: {
    body: {
      type: 'array',
      items: { $ref: 'http://example.com#/properties/hello' }
    }
  }
})
// 作为根引用
fastify.addSchema({
  $id: 'commonSchema',
  type: 'object',
  properties: {
    hello: { type: 'string' }
  }
})

fastify.post('/', {
  handler () {},
  schema: {
    body: { $ref: 'commonSchema#' },
    headers: { $ref: 'commonSchema#' }
  }
})

获取共用Schema

  • 当自定义验证器或序列化器的时候,Fastify 不再能控制它们,此时 .addSchema 方法失去了作用
fastify.addSchema({
  $id: 'schemaId',
  type: 'object',
  properties: {
    hello: { type: 'string' }
  }
})

const mySchemas = fastify.getSchemas()
const mySchema = fastify.getSchema('schemaId')

验证