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.
 
 
 
 
 
 

285 lines
6.1 KiB

> 更新比较慢的版本,先熟悉这个教程和这个框架
> [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')
```
## 验证