> 更新比较慢的版本,先熟悉这个教程和这个框架 > [fastify/docs-chinese: Fastify 中文文档 (github.com)](https://github.com/fastify/docs-chinese) # 开始 准备 ```bash npm init -y # 运行处加入 "build": "tsc -p tsconfig.json", npx tsc --init pnpm i -S fastify pnpm i -D typescript @types/node ``` ```ts // 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() ``` 运行 ```bash npm run build node started.js ``` # 路由 ## 完整格式 ```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里面都写了处理函数会报错 ```js const opts = { schema: { response: { 200: { type: 'object', properties: { hello: { type: 'string' } } } } } } fastify.get('/', opts, (request, reply) => { reply.send({ hello: 'world' }) }) ``` ## URL构建 - Fastify 同时支持静态与动态的 URL - 要注册一个**参数命名**的路径,请在参数名前加上_冒号_。_星号_表示**通配符**。 _注意,静态路由总是在参数路由和通配符之前进行匹配_ ```js // 参数路由 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)`同时使用只会发送第一次,同时还会触发警告日志,因为你试图发送两次响应。 ```js fastify.get('/', options, async function (request, reply) { setImmediate(() => { reply.send({ hello: 'world' }) }) await reply // return reply }) ``` ## 路由前缀 ```js // 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) ``` ```js // routes/v1/users.js module.exports = function (fastify, opts, done) { fastify.get('/user', handler_v1) done() } ``` ```js // routes/v2/users.js module.exports = function (fastify, opts, done) { fastify.get('/user', handler_v2) done() } ``` ## 自定义日志级别 - 可以在统一路由加入打印固定字段的,但是非必要 ```js // 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中定义 ```js fastify.get('/', { logLevel: 'warn' }, (request, reply) => { reply.send({ hello: 'world' }) }) ``` # 装饰器 ```js fastify.decorate('utility', function () { // 新功能的代码 }) fastify.decorate('conf', { db: 'some.db', port: 3000 }) // 通过装饰属性的名称便可访问值: fastify.utility() console.log(fastify.conf.db) ``` 路由函数的 `this` 指向 Fastify server ```js fastify.decorate('db', new DbConnection()) fastify.get('/', async function (request, reply) { reply({hello: await this.db.query('world')}) }) ``` ## 检查装饰器的存在 用于检查服务器实例上是否存在某个装饰器: ```js // 用于检查服务器实例上是否存在某个装饰器: 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'` 的对象。 ```js 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` 方法失去了作用 ```js fastify.addSchema({ $id: 'schemaId', type: 'object', properties: { hello: { type: 'string' } } }) const mySchemas = fastify.getSchemas() const mySchema = fastify.getSchema('schemaId') ``` ## 验证