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