Fastify系列教程四(求对象、响应对象和插件)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Fastify系列教程四(求对象、响应对象和插件)
Fastify 系列教程:
响应对象
路由的第⼆个参数即是响应对象reply,它有如下⼏个⽅法:
.code(statusCode) - 设置状态码。

.header(name, value) - 设置响应头。

.type(value) - 设置Content-Type字段。

.redirect([code,] url) - 重定向到特定的地址,code参数是可选的 (默认为302)。

.serializer(function) - 为有效荷载设置⾃定义的序列化器。

.send(payload) - 向客户端发送荷载,可以是⽂本、JSON、流或者⼀个错误对象。

.sent - ⼀个布尔值,⽤来判断send函数是否已经被调⽤。

⽰例:
fastify.get('/', options, function (request, reply) {
// Your code
reply
.code(200)
.header('Content-Type', 'application/json')
.send({ hello: 'world' })
})
Code
如果没有设置reply.code,默认statusCode是 200。

Header设置响应头
设置⾃定义的响应头。

如果没有设置'Content-Type'字段,Fastify 猜测你会使⽤'application/json',除⾮你要发送⼀个流,在这种情况下,Fastify会识别并设置'Content-Type'为'application/octet-stream'。

注意,如果使⽤的序列化器不是序列化到 JSON,则必须设置⾃定义的Content-Type头。

Redirect
重定向⼀个请求到特定的地址,状态码是可选的,默认为302。

reply.redirect('/home')
Type
设置响应头的Content-Type字段。

这是reply.header('Content-Type', 'the/type')的简写。

reply.type('text/html')
Serializer
Fastify 作为⼀个完整的JSON兼容服务器⽽诞⽣,所以可以直接序列化send()函数中的有效荷载。

如果你设置了输出 schema,那么会使⽤作为格式化JSON的⼯具包,否则使⽤。

如果想使⽤⾃定义的序列化器,⽐如或者,你可以使⽤.serializer(),注意:如果使⽤⾃定义的序列化器却不是序列化成JSON,那么必须得设置⾃定义的'Content-Type'头。

reply
.header('Content-Type', 'application/x-protobuf')
.serializer(protoBuf.serialize)
Promises
发送原⽣的 promises 和⽀持开箱即⽤的async-await。

fastify.get('/promises', options, function (request, reply) {
const promise = new Promise(function(){
setTimeout(function(resolve, reject){
resolve({hello: 'promise'})
}, 1000)
})
reply
.code(200)
.send(promise)
})
// 上述代码将会在服务端延迟 1s 后成功响应 {hello: 'promise'}
fastify.get('/async-await', options, async function (request, reply) {
var res = await new Promise(function (resolve) {
setTimeout(resolve, 200, { hello: 'world' })
})
return res
})
Streams
也可以发送流,内部使⽤来避免⽂件描述符的泄露。

如果你要发送流,并且尚未设置“Content-Type”头,则 send 将会以“application/octet-stream”进⾏设置。

fastify.get('/streams', function (request, reply) {
const fs = require('fs')
const stream = fs.createReadStream('some-file', 'utf8')
reply.send(stream)
})
Errors
如果你向 send 函数传⼊⼀个 Error 对象的实例,Fastify 将⾃动创建⼀个结构如下的错误
{
error: String // the http error message
message: String // the user error message
statusCode: Number // the http status code
}
fastify.get('/error', function(request. reply){
reply.send(new Error('error request'))
})
如果你想要扩展错误对象,可以使⽤
如果你传⼊错误对象并且设置⼩于 400 的状态码,Fastify 将会⾃动的设置成 500。

请求对象
路由的第⼀个参数即是请求对象request,它有如下⼏个属性:
query - 解析后的查询字符串
body - 请求体
params - 匹配url的参数,例如: ⽤/page/5匹配/page/:id => {id: 5}
headers - 请求头对象
req - 原⽣Node的请求对象
log - ⽇志记录器的实例
fastify.post('/page/:id', options, function (request, reply) {
console.log(request.body)
console.log(request.query)
console.log(request.params)
console.log(request.headers)
console.log(request.req)
('some info')
})
插件
Fastify 允许⽤户使⽤插件扩展其功能。

⼀个插件可以是⼀组路由,⼀个装饰器等,可以使⽤register函数注册插件。

默认情况下,register创建了⼀个新的作⽤域,这意味着如果对 Fastify 实例(通过decorate)进⾏⼀些更改,则此更改不会反映到当前上下⽂的祖先中,⽽只会反映到其⼦节点。

这个特性允许我们实现插件封装和继承,这样就创建了⼀个直接⾮循环图(DAG),就不会有交叉依赖
关系引起的问题。

创建⼀个插件
创建插件⾮常简单,你只要创建⼀个包含三个参数的⽅法。

第⼀个是 fastify 实例,第⼆个是⼀个配置对象,最后⼀个是 next 回调。

// plugin.js
module.exports = function (fastify, opts, next) {
fastify.decorate('utility', () => {})
fastify.get('/', handler)
next()
}
使⽤插件:
var plugin = require('./plugin')
var fastify = require('fastify')()
fastify.register(plugin)
注意,插件是有作⽤域的:
fastify.register((instance, opts, next) => {
instance.decorate('util', (a, b) => a + b)
console.log(instance.util('that is ', ' awesome'))
next()
})
fastify.register((instance, opts, next) => {
console.log(instance.util('that is ', ' awesome')) // 抛出异常
next()
})
在第⼆个 register 函数中instance.util会抛出异常,因为 util 只存在于第⼀个 register 函数的上下⽂中。

注意:封装只适⽤于祖先和兄弟作⽤域,不适⽤于⼦作⽤域。

fastify.register((instance, opts, next) => {
instance.decorate('util', (a, b) => a + b)
console.log(instance.util('that is ', ' awesome'))
fastify.register((instance, opts, next) => {
console.log(instance.util('that is ', ' awesome')) // 不会抛出异常
next()
})
next()
})
fastify.register((instance, opts, next) => {
console.log(instance.util('that is ', ' awesome')) // 会抛出异常
next()
})
如果希望定义的⽅法在应⽤的任何地⽅都可以⽤,没有作⽤域的影响,则可以在根作⽤域中定义。

或者使⽤fastify-plugin来包装插件。

使⽤fastify-plugin模块,可以传递⼀个表⽰ Fastify 的版本范围的参数作为插件将⽀持的 Fastify 版本。

const fp = require('fastify-plugin')
const plugin = fp(function (fastify, opts, next) {
fastify.decorate('utility', (a, b) => {
return a + b
})
next()
}, ">=0.30.2")
fastify.register(plugin)
fastify.register(function(fastify, opts, next){
console.log(fastify.utility(1, 3)) // 4
next()
})
在插件中使⽤路由钩⼦
只在某些特定的路由中执⾏路由钩⼦,可以这样做:
fastify.register((instance, opts, next) => {
instance.decorate('util', (req, key, value) => { req.key = value })
instance.addHook('preHandler', (req, reply, done) => {
instance.util(req, 'timestamp', new Date())
done()
})
instance.get('/plugin1', (req, reply) => {
reply.send(req)
})
next()
})
fastify.get('/plugin2', (req, reply) => {
reply.send(req)
})
/plugin2将不会应⽤preHandler钩⼦。

常⽤插件
模板引擎
安装
npm install point-of-view --save
使⽤⽅法
fastify.register(require('point-of-view'), {
engine: {
ejs: require('ejs')
},
templates: './views' // 模板存放的⽬录
})
fastify.get('/', (req, reply) => {
reply.view('index.ejs', { text: 'text' })
})
Cookie
安装
npm install fastify-cookie --save
使⽤⽅法
const fastify = require('fastify')()
fastify.register(require('fastify-cookie'), (err) => {
if (err) throw err
})
fastify.get('/', (req, reply) => {
const cookieFoo = req.cookies.foo // 得到发送过来的cookie中的foo字段
reply
.setCookie('foo', 'foo', { // 设置cookie
domain: '',
path: '/'
})
.send({hello: 'world'})
})
内容类型⽀持 application/x-www-form-urlencoded 内容类型安装
npm install fastify-formbody --save
使⽤⽅式
const fastify = require('fastify')()
fastify.register(require('fastify-formbody'), {}, (err) => { if (err) throw err
})
fastify.post('/', (req, reply) => {
reply.send(req.body)
})
fastify.listen(8000, (err) => {
if (err) throw err
})
更多插件可以访问
Fastify 系列教程到此结束。

Tips:访问查看我翻译的 Fastify 中⽂⽂档。

相关文档
最新文档