處理函數(shù)的第二個參數(shù)為 Reply。 Reply 是 Fastify 的一個核心對象。它暴露了以下函數(shù)及屬性:
fastify.get('/', options, function (request, reply) {
// 你的代碼
reply
.code(200)
.header('Content-Type', 'application/json; charset=utf-8')
.send({ hello: 'world' })
})
另外,Reply 能夠訪問請求的上下文:
fastify.get('/', {config: {foo: 'bar'}}, function (request, reply) {
reply.send('handler config.foo = ' + reply.context.config.foo)
})
如果沒有設(shè)置 reply.code,statusCode 會是 200。
獲取或設(shè)置 HTTP 狀態(tài)碼。作為 setter 使用時,是 reply.code() 的別名。
if (reply.statusCode >= 299) {
reply.statusCode = 500
}
設(shè)置響應(yīng) header。如果值被省略或為 undefined,將被強制設(shè)成 ''。
更多信息,請看 http.ServerResponse#setHeader。
獲取已設(shè)置的 header 的值。
reply.header('x-foo', 'foo') // 設(shè)置 x-foo header 的值為 foo
reply.getHeader('x-foo') // 'foo'
清除已設(shè)置的 header 的值。
reply.header('x-foo', 'foo')
reply.removeHeader('x-foo')
reply.getHeader('x-foo') // undefined
返回一個 boolean,用于檢查是否設(shè)置了某個 header。
重定向請求至指定的 url,狀態(tài)碼可選,當(dāng)未通過 code 方法設(shè)置時,默認為 302。
reply.redirect('/home')
調(diào)用自定義的 not found 處理函數(shù)。
reply.callNotFound()
調(diào)用自定義響應(yīng)時間獲取函數(shù),來計算自收到請求起的時間。
const milliseconds = reply.getResponseTime()
設(shè)置響應(yīng)的 content type。 這是 reply.header('Content-Type', 'the/type') 的簡寫。
reply.type('text/html')
.send() 方法會默認將 Buffer、stream、string、undefined、Error 之外類型的值 JSON-序列化。假如你需要在特定的請求上使用自定義的序列化工具,你可以通過 .serializer() 來實現(xiàn)。要注意的是,如果使用了自定義的序列化工具,你必須同時設(shè)置 'Content-Type' header。
reply
.header('Content-Type', 'application/x-protobuf')
.serializer(protoBuf.serialize)
注意,你并不需要在一個 handler 內(nèi)部使用這一工具,因為 Buffers、streams 以及字符串 (除非已經(jīng)設(shè)置了序列化工具) 被認為是已序列化過的。
reply
.header('Content-Type', 'application/x-protobuf')
.send(protoBuf.serialize(data))
請看 .send() 了解更多關(guān)于發(fā)送不同類型值的信息。
如你所見,.sent 屬性表明是否已通過 reply.send() 發(fā)送了一個響應(yīng)。
當(dāng)控制器是一個 async 函數(shù)或返回一個 promise 時,可以手動設(shè)置 reply.sent = true,以防 promise resolve 時自動調(diào)用 reply.send()。通過設(shè)置 reply.sent = true,程序能完全掌控底層的請求,且相關(guān)鉤子不會被觸發(fā)。
請看范例:
app.get('/', (req, reply) => {
reply.sent = true
reply.res.end('hello world')
return Promise.resolve('this will be skipped') // 譯注:該處會被跳過
})
如果處理函數(shù) reject,將會記錄一個錯誤。
顧名思義,.send() 是向用戶發(fā)送 payload 的函數(shù)。
如上文所述,如果你發(fā)送 JSON 對象時,設(shè)置了輸出的 schema,那么 send 會使用 fast-json-stringify 來序列化對象。否則,將使用 JSON.stringify()。
fastify.get('/json', options, function (request, reply) {
reply.send({ hello: 'world' })
})
在未設(shè)置 Content-Type 的時候,字符串會以 text/plain; charset=utf-8 類型發(fā)送。如果設(shè)置了 Content-Type,且使用自定義序列化工具,那么 send 發(fā)出的字符串會被序列化。否則,字符串不會有任何改動 (除非 Content-Type 的值為 application/json; charset=utf-8,這時,字符串會像對象一樣被 JSON-序列化,正如上一節(jié)所述)。
fastify.get('/json', options, function (request, reply) {
reply.send('plain string')
})
send 開箱即用地支持 stream。它使用 pump 來避免文件描述符 (file descriptors) 的泄露。如果在未設(shè)置 'Content-Type' header 的情況下發(fā)送 stream,它會被設(shè)定為 'application/octet-stream'。
fastify.get('/streams', function (request, reply) {
const fs = require('fs')
const stream = fs.createReadStream('some-file', 'utf8')
reply.send(stream)
})
未設(shè)置 'Content-Type' header 的情況下發(fā)送 buffer,send 會將其設(shè)置為 'application/octet-stream'。
const fs = require('fs')
fastify.get('/streams', function (request, reply) {
fs.readFile('some-file', (err, fileBuffer) => {
reply.send(err || fileBuffer)
})
})
若使用 send 發(fā)送一個 Error 的實例,F(xiàn)astify 會自動創(chuàng)建一個如下的錯誤結(jié)構(gòu):
{
error: String // http 錯誤信息
code: String // Fastify 的錯誤代碼
message: String // 用戶錯誤信息
statusCode: Number // http 狀態(tài)碼
}
你可以向 Error 對象添加自定義屬性,例如 headers,這可以用來增強 http 響應(yīng)。注意:如果 send 一個錯誤,但狀態(tài)碼小于 400,F(xiàn)astify 會自動將其設(shè)為 500。
貼士:你可以通過 http-errors 或 fastify-sensible 來簡化生成的錯誤:
fastify.get('/', function (request, reply) {
reply.send(httpErrors.Gone())
})
如果你想完全自定義錯誤處理,請看 setErrorHandler API。注:當(dāng)自定義錯誤處理時,你需要自行記錄日志
API:
fastify.setErrorHandler(function (error, request, reply) {
request.log.warn(error)
var statusCode = error.statusCode >= 400 ? error.statusCode : 500
reply
.code(statusCode)
.type('text/plain')
.send(statusCode >= 500 ? 'Internal server error' : error.message)
})
路由生成的 not found 錯誤會使用 setNotFoundHandler。 API:
fastify.setNotFoundHandler(function (request, reply) {
reply
.code(404)
.type('text/plain')
.send('a custom not found')
})
發(fā)送的 payload (序列化之后、經(jīng)過任意的 onSend 鉤子) 必須為下列類型之一,否則將會拋出一個錯誤:
Fastify 原生地處理 promise 并支持 async-await。請注意,在下面的例子中我們沒有使用 reply.send。
const delay = promisify(setTimeout)
fastify.get('/promises', options, function (request, reply) {
return delay(200).then(() => { return { hello: 'world' }})
})
fastify.get('/async-await', options, async function (request, reply) {
await delay(200)
return { hello: 'world' }
})
被 reject 的 promise 默認發(fā)送 500 狀態(tài)碼。要修改回復(fù),可以 reject 一個 promise,或在 async 函數(shù) 中進行 throw 操作,同時附帶上一個有 statusCode (或 status) 與 message 屬性的對象。
fastify.get('/teapot', async function (request, reply) => {
const err = new Error()
err.statusCode = 418
err.message = 'short and stout'
throw err
})
想要了解更多?請看 Routes#async-await。
顧名思義,Reply 對象能被等待。換句話說,await reply 將會等待,直到回復(fù)被發(fā)送。 如上的 await 語法調(diào)用了 reply.then()。
reply.then(fullfilled, rejected) 接受兩個參數(shù):
更多細節(jié),請看:
更多建議: