关于 fastify-v5
面向使用 Fastify v5 和 TypeScript 的开发者,提供基于 TypeBox 的类型安全路由、插件、钩子与测试实践。指南涵盖从模式定义生成 OpenAPI,以及用 inject() 测试路由。
主要功能
- 01用 TypeBox 定义请求与响应模式
- 02从模式推断路由类型
- 03从模式生成 OpenAPI
- 04开发插件并使用请求钩子
- 05通过 inject() 测试路由
适用场景
- 01构建类型安全的 Fastify API
- 02为路由生成 OpenAPI 规范
- 03编写可复用插件与请求生命周期逻辑
- 04对路由进行黑盒测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ blockmatic/ basilic-skills --skill fastify-v5安装后在 Claude Code 中输入/fastify-v5确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/hooks.mdinstance-config.mdopenapi-integration.mdplugins.mdtesting.mdtemplates/hook-plugin.tsplugin.tsroute-schema.tstest-utils.ts详细介绍
技能:fastify
适用范围
- 适用于:Fastify v5+、TypeBox schemas、类型安全的路由定义、自动生成 OpenAPI、插件、钩子、测试
- 不适用于:数据库集成(请参阅 drizzle-orm)
前提条件
- Fastify v5+
- 使用
@fastify/type-provider-typebox作为 TypeBox 类型提供程序 - 使用
@sinclair/typebox定义 schema - TypeScript v5+,并启用严格模式
原则
- 使用 TypeBox schemas 验证路由(params、query、body、response)
- 使用
TypeBoxTypeProvider自动从 schemas 推断类型 - 为所有状态码定义 response schemas
- 使用 schemas 生成 OpenAPI(通过
@fastify/swagger) - 请求类型(
request.params、request.query、request.body)从 schemas 推断 - 根据 schema 自动进行响应验证
约束
必须
- 使用
TypeBoxTypeProvider确保类型安全:fastify.withTypeProvider<TypeBoxTypeProvider>() - 为所有状态码定义 response schemas
- 使用 TypeBox
Type.*构造函数定义 schema
应当
- 在路由 schemas 中使用
operationId生成 OpenAPI - 使用
tags在 OpenAPI 文档中组织路由 - 为错误情况定义错误响应 schemas
避免
- 手动进行类型断言(类型会从 schemas 推断)
- 跳过 response schema 定义
- 在同一路由中混用 TypeBox 和其他 schema 库
交互
- 与 drizzle-orm 配合进行数据库集成
- 生成与 openapi-ts 代码生成兼容的 OpenAPI 规范
模式
路由 Schema 模式
import { Type } from '@sinclair/typebox'
import type { FastifyPluginAsync } from 'fastify'
const UserSchema = Type.Object({
id: Type.String(),
email: Type.String({ format: 'email' }),
name: Type.String(),
})
const userRoutes: FastifyPluginAsync = async fastify => {
fastify.get('/users/:id', {
schema: {
operationId: 'getUser',
params: Type.Object({ id: Type.String() }),
response: {
200: UserSchema,
404: Type.Object({ code: Type.String(), message: Type.String() }),
},
},
}, async (request, reply) => {
// request.params.id is typed
const { id } = request.params
return reply.send(user)
})
}
Schema 类型
Type.String()
Type.Number()
Type.Boolean()
Type.Object({ id: Type.String() })
Type.Array(Type.String())
Type.Optional(Type.String())
Type.Union([Type.String(), Type.Number()])
完整示例请参阅路由 Schema 模板。
实例配置
使用 TypeBox 类型提供程序、logger 和请求设置配置 Fastify 实例:
import type { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
import Fastify, { LogController } from 'fastify'
const fastify = Fastify({
logger: {
level: 'info',
transport: process.env.NODE_ENV === 'development' ? {
target: 'pino-pretty',
} : undefined,
},
trustProxy: true,
bodyLimit: 1048576, // 1MB
requestTimeout: 30000,
requestIdHeader: 'x-request-id',
logController: new LogController({ requestIdLogLabel: 'reqId', disableRequestLogging: false }),
}).withTypeProvider<TypeBoxTypeProvider>()
完整配置请参阅实例配置。
插件开发
使用 fastify-plugin 创建可复用插件,实现非封装行为:
import type { FastifyPluginAsync } from 'fastify'
import fp from 'fastify-plugin'
const myPlugin: FastifyPluginAsync = async fastify => {
// Plugin logic
}
export default fp(myPlugin, {
name: 'my-plugin',
})
钩子(请求生命周期)
使用钩子拦截请求、修改响应或处理错误:
fastify.addHook('onRequest', async (request, reply) => {
// Add security headers, logging, etc.
})
fastify.addHook('onResponse', async (request, reply) => {
// Modify response, add headers, etc.
})
fastify.addHook('onError', async (request, reply, error) => {
// Handle errors
})
使用 inject() 进行测试
使用 Fastify 的 inject() 方法测试路由,进行黑盒测试:
const response = await fastify.inject({
method: 'GET',
url: '/users/123',
})
expect(response.statusCode).toBe(200)
const data = JSON.parse(response.body)
流式响应
处理流式响应(例如,Server-Sent Events、文本流):
fastify.post('/stream', {
schema: {
response: {
200: Type.String({ description: 'Streaming response' }),
},
},
}, async (request, reply) => {
reply.header('Content-Type', 'text/event-stream')
reply.header('Cache-Control', 'no-cache')
return reply.send(stream)
})
常用插件
速率限制
import rateLimit from '@fastify/rate-limit'
await fastify.register(rateLimit, {
max: 100,
timeWindow: 60000,
keyGenerator: request => request.ip,
})
CORS
import cors from '@fastify/cors'
await fastify.register(cors, {
origin: (origin, callback) => {
// Validate origin
callback(null, true)
},
credentials: false,
})
错误处理器
fastify.setErrorHandler((error, request, reply) => {
// Global error handling
reply.status(error.statusCode ?? 500).send({
code: 'ERROR',
message: error.message,
})
})
优雅关闭
处理进程信号以实现优雅关闭:
const shutdown = async (signal: string) => {
fastify.log.info({ signal }, 'Shutting down')
await fastify.close()
process.exit(0)
}
process.on('SIGTERM', () => shutdown('SIGTERM'))
process.on('SIGINT', () => shutdown('SIGINT'))
AutoLoad 模式
使用 @fastify/autoload 自动发现插件和路由:
import AutoLoad from '@fastify/autoload'
await fastify.register(AutoLoad, {
dir: path.join(__dirname, 'plugins'),
forceESM: true,
})
参考资料
- OpenAPI 集成 - OpenAPI 生成模式
- 插件模式 - 使用 fastify-plugin 开发插件
- 钩子指南 - 请求生命周期钩子
- 测试模式 - 使用 inject() 进行测试
- 实例配置 - Fastify 实例设置
评论
支持 Markdown