跳至主要內容
版本:最新版 (v5.0.x)

伺服器 (Server)

工廠函式 (Factory)

Fastify 模組會匯出一個工廠函式,用於建立新的

Fastify 伺服器實例。此工廠函式會接受一個選項物件,用於自訂產生的實例。本文件描述該選項物件中可用的屬性。

http

  • 預設值:null

用於設定伺服器監聽 socket 的物件。選項與 Node.js 核心 createServer 方法相同。

如果設定了 http2https 選項,則會忽略此選項。

http2

  • 預設值:false

如果為 true,則會使用 Node.js 核心的 HTTP/2 模組來綁定 socket。

https

  • 預設值:null

用於設定伺服器監聽 TLS 的 socket 物件。選項與 Node.js 核心 createServer 方法相同。當此屬性為 null 時,socket 將不會設定為 TLS。

當設定 http2 選項時,此選項也適用。

connectionTimeout

  • 預設值:0 (無逾時)

定義伺服器逾時時間,以毫秒為單位。請參閱 server.timeout 屬性的文件,以了解此選項的效果。

當指定 serverFactory 選項時,將會忽略此選項。

keepAliveTimeout

  • 預設值:72000 (72 秒)

定義伺服器保持連線逾時時間,以毫秒為單位。請參閱 server.keepAliveTimeout 屬性的文件,以了解此選項的效果。此選項僅適用於使用 HTTP/1 時。

當指定 serverFactory 選項時,將會忽略此選項。

forceCloseConnections

  • 預設值:如果 HTTP 伺服器允許,則為 "idle",否則為 false

當設定為 true 時,在 close 時,伺服器會迭代目前持續連線,並銷毀其 socket

警告 不會檢查連線以判斷請求是否已完成。

如果支援,Fastify 會優先使用 HTTP 伺服器的 closeAllConnections 方法,否則會使用內部連線追蹤。

當設定為 "idle" 時,在 close 時,伺服器會迭代目前未發送請求或等待回應的持續連線,並銷毀其 socket。如果 HTTP 伺服器支援 closeIdleConnections 方法,則僅支援此值,否則嘗試設定它將會擲回例外狀況。

maxRequestsPerSocket

  • 預設值:0 (無限制)

定義 socket 在關閉保持連線之前可以處理的最大請求數。請參閱 server.maxRequestsPerSocket 屬性以了解此選項的效果。此選項僅適用於使用 HTTP/1.1 時。此外,當指定 serverFactory 選項時,將會忽略此選項。

注意 在撰寫本文時,只有 node >= v16.10.0 支援此選項。

requestTimeout

  • 預設值:0 (無限制)

定義從用戶端接收整個請求的最大毫秒數。請參閱 server.requestTimeout 屬性以了解此選項的效果。

當指定 serverFactory 選項時,將會忽略此選項。必須將其設定為非零值 (例如 120 秒),以防止在伺服器部署時未在前端使用反向 Proxy 的情況下,發生潛在的阻斷服務攻擊。

注意 在撰寫本文時,只有 node >= v14.11.0 支援此選項。

ignoreTrailingSlash

  • 預設值:false

Fastify 使用 find-my-way 來處理路由。預設情況下,Fastify 會將尾部的斜線納入考量。路徑如 /foo/foo/ 會被視為不同的路徑。如果您想要變更此設定,請將此旗標設定為 true。這樣,/foo/foo/ 都會指向相同的路由。此選項適用於產生的伺服器實例的所有路由註冊。

const fastify = require('fastify')({
ignoreTrailingSlash: true
})

// registers both "/foo" and "/foo/"
fastify.get('/foo/', function (req, reply) {
reply.send('foo')
})

// registers both "/bar" and "/bar/"
fastify.get('/bar', function (req, reply) {
reply.send('bar')
})

ignoreDuplicateSlashes

  • 預設值:false

Fastify 使用 find-my-way 來處理路由。您可以使用 ignoreDuplicateSlashes 選項從路徑中移除重複的斜線。它會移除路由路徑和請求 URL 中的重複斜線。此選項適用於產生的伺服器實例的所有路由註冊。

ignoreTrailingSlashignoreDuplicateSlashes 都設定為 true 時,Fastify 會先移除重複的斜線,然後移除尾部的斜線,這表示 //a//b//c// 將會轉換為 /a/b/c

const fastify = require('fastify')({
ignoreDuplicateSlashes: true
})

// registers "/foo/bar/"
fastify.get('///foo//bar//', function (req, reply) {
reply.send('foo')
})

maxParamLength

  • 預設值:100

您可以使用 maxParamLength 選項為參數路由 (標準、正規表示式和多重) 中的參數設定自訂長度;預設值為 100 個字元。如果達到最大長度限制,則會叫用找不到的路由。

如果您有基於正規表示式的路由,這會特別有用,可以保護您免受 ReDoS 攻擊

bodyLimit

  • 預設值:1048576 (1MiB)

定義伺服器允許接受的最大酬載 (以位元組為單位)。如果主體大小超出此限制,預設主體讀取器會傳送 FST_ERR_CTP_BODY_TOO_LARGE 回應。如果提供 preParsing 鉤子,則此限制會套用至鉤子傳回的串流大小 (即「解碼」主體的大小)。

onProtoPoisoning

  • 預設值:'error'

定義在剖析具有 __proto__ 的 JSON 物件時,框架必須採取的動作。此功能由 secure-json-parse 提供。請參閱 原型汙染,以取得有關原型汙染攻擊的更多詳細資訊。

可能的值為 'error''remove''ignore'

onConstructorPoisoning

  • 預設值:'error'

定義當解析帶有 constructor 的 JSON 物件時,框架必須採取的動作。此功能由 secure-json-parse 提供。關於原型污染攻擊的更多詳細資訊,請參閱 原型污染

可能的值為 'error''remove''ignore'

logger

Fastify 透過 Pino 記錄器內建了日誌記錄功能。此屬性用於配置內部記錄器實例。

此屬性可能的值如下:

  • 預設值:false。日誌記錄功能已停用。所有日誌記錄方法都會指向一個空的記錄器 abstract-logging 實例。

  • pinoInstance:一個先前已實例化的 Pino 實例。內部記錄器將指向此實例。

  • object:一個標準的 Pino 選項物件。這將直接傳遞給 Pino 建構函式。如果物件中不存在以下屬性,則會相應地新增這些屬性:

    • level:最小日誌記錄層級。如果未設定,則會設定為 'info'
    • serializers:序列化函式的雜湊。預設情況下,會為 req(傳入的要求物件)、res(傳出的回應物件)和 err(標準 Error 物件)新增序列化器。當日誌方法收到具有任何這些屬性的物件時,將針對該屬性使用各自的序列化器。例如:
      fastify.get('/foo', function (req, res) {
      req.log.info({req}) // log the serialized request object
      res.send('foo')
      })
      任何使用者提供的序列化器都會覆寫相應屬性的預設序列化器。
  • loggerInstance:一個自訂記錄器實例。記錄器必須符合 Pino 介面,具有以下方法:infoerrordebugfatalwarntracechild。例如:

    const pino = require('pino')();

    const customLogger = {
    info: function (o, ...n) {},
    warn: function (o, ...n) {},
    error: function (o, ...n) {},
    fatal: function (o, ...n) {},
    trace: function (o, ...n) {},
    debug: function (o, ...n) {},
    child: function() {
    const child = Object.create(this);
    child.pino = pino.child(...arguments);
    return child;
    },
    };

    const fastify = require('fastify')({logger: customLogger});

disableRequestLogging

  • 預設值:false

當啟用日誌記錄時,Fastify 會在收到要求時以及已傳送該要求的回應時發出 info 層級的日誌訊息。透過將此選項設定為 true,將停用這些日誌訊息。這允許透過附加自訂的 onRequestonResponse 鉤子來進行更彈性的要求開始和結束記錄。

將停用的其他日誌項目是:

  • 預設 onResponse 鉤子在回覆回呼錯誤時寫入的錯誤日誌
  • defaultErrorHandler 在錯誤管理時寫入的錯誤和資訊日誌
  • 當請求不存在的路由時,fourOhFour 處理常式寫入的資訊日誌

Fastify 發出的其他日誌訊息將保持啟用狀態,例如棄用警告和在伺服器關閉時收到要求時發出的訊息。

// Examples of hooks to replicate the disabled functionality.
fastify.addHook('onRequest', (req, reply, done) => {
req.log.info({ url: req.raw.url, id: req.id }, 'received request')
done()
})

fastify.addHook('onResponse', (req, reply, done) => {
req.log.info({ url: req.raw.originalUrl, statusCode: reply.raw.statusCode }, 'request completed')
done()
})

serverFactory

您可以使用 serverFactory 選項將自訂 HTTP 伺服器傳遞給 Fastify。

serverFactory 是一個函式,它接受一個 handler 參數,該參數接受 requestresponse 物件作為參數,以及一個選項物件,該物件與您傳遞給 Fastify 的物件相同。

const serverFactory = (handler, opts) => {
const server = http.createServer((req, res) => {
handler(req, res)
})

return server
}

const fastify = Fastify({ serverFactory })

fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' })
})

fastify.listen({ port: 3000 })

在內部,Fastify 使用 Node 核心 HTTP 伺服器的 API,因此如果您使用自訂伺服器,則必須確保公開相同的 API。如果沒有,您可以在 return 語句之前,在 serverFactory 函式內部增強伺服器實例。

caseSensitive

  • 預設值:true

當為 true 時,路由會註冊為區分大小寫。也就是說,/foo 不等於 /Foo。當為 false 時,路由會區分大小寫。

請注意,將此選項設定為 false 會違反 RFC3986

透過將 caseSensitive 設定為 false,所有路徑都會以小寫形式比對,但是路由參數或萬用字元會保持其原始的字母大小寫。此選項不影響查詢字串,請參閱 querystringParser 來變更它們的處理方式。

fastify.get('/user/:username', (request, reply) => {
// Given the URL: /USER/NodeJS
console.log(request.params.username) // -> 'NodeJS'
})

allowUnsafeRegex

  • 預設值:false

預設為停用,因此路由僅允許安全的正規表示式。若要使用不安全的表示式,請將 allowUnsafeRegex 設定為 true

fastify.get('/user/:id(^([0-9]+){4}$)', (request, reply) => {
// Throws an error without allowUnsafeRegex = true
})

requestIdHeader

  • 預設值:'request-id'

用於設定要求 ID 的標頭名稱。請參閱 要求 ID 部分。將 requestIdHeader 設定為 true 會將 requestIdHeader 設定為 "request-id"。將 requestIdHeader 設定為非空字串會使用指定的字串作為 requestIdHeader。預設情況下,requestIdHeader 設定為 false,並會立即使用 genReqId。將 requestIdHeader 設定為空字串 ("") 會將 requestIdHeader 設定為 false

  • 預設值:false
const fastify = require('fastify')({
requestIdHeader: 'x-custom-id', // -> use 'X-Custom-Id' header if available
//requestIdHeader: false, // -> always use genReqId
})

requestIdLogLabel

  • 預設值:'reqId'

定義在記錄要求時用於要求識別碼的標籤。

genReqId

  • 預設值:如果提供 'request-id' 標頭的值,或單調遞增的整數

用於產生要求 ID 的函式。它會收到 *原始* 傳入的要求作為參數。預期此函式不會發生錯誤。

尤其在分散式系統中,您可能需要覆寫預設的 ID 產生行為,如下所示。若要產生 UUID,您可能需要查看 hyperid

注意 如果在

[requestIdHeader](#requestidheader) 中設定的標頭可用(預設為 'request-id'),則不會呼叫 genReqId
let i = 0
const fastify = require('fastify')({
genReqId: function (req) { return i++ }
})

trustProxy

  • 預設值:false
  • true/false:信任所有 Proxy (true) 或不信任任何 Proxy (false)。
  • string:僅信任給定的 IP/CIDR (例如 '127.0.0.1')。可能是逗號分隔值的清單 (例如 '127.0.0.1,192.168.1.1/24')。
  • Array<string>:僅信任給定的 IP/CIDR 清單 (例如 ['127.0.0.1'])。
  • number:信任來自前端 Proxy 伺服器的第 n 個躍點作為用戶端。
  • Function:自訂信任函式,它接受 address 作為第一個引數
    function myTrustFn(address, hop) {
    return address === '1.2.3.4' || hop === 1
    }

透過啟用 trustProxy 選項,Fastify 將知道它位於 Proxy 後面,並且 X-Forwarded-* 標頭欄位可能是可信任的,否則可能會很容易被偽造。

const fastify = Fastify({ trustProxy: true })

如需更多範例,請參閱 proxy-addr 套件。

您可以存取 request 物件上的 ipipshostprotocol 值。

fastify.get('/', (request, reply) => {
console.log(request.ip)
console.log(request.ips)
console.log(request.host)
console.log(request.protocol)
})

注意 如果要求包含多個 x-forwarded-hostx-forwarded-proto 標頭,則僅使用最後一個來衍生 request.hostnamerequest.protocol

pluginTimeout

  • 預設值:10000

外掛程式可以載入的最大時間(以毫秒為單位)。如果未載入,則 ready 將完成並產生代碼為 'ERR_AVVIO_PLUGIN_TIMEOUT'Error。當設定為 0 時,會停用此檢查。這會控制 avviotimeout 參數。

querystringParser

Fastify 使用的預設查詢字串剖析器是 Node.js 的核心 querystring 模組。

您可以使用此選項來使用自訂剖析器,例如 qs

如果您只希望金鑰(而不是值)不區分大小寫,我們建議使用自訂剖析器來僅將金鑰轉換為小寫。

const qs = require('qs')
const fastify = require('fastify')({
querystringParser: str => qs.parse(str)
})

您也可以使用 Fastify 的預設剖析器,但變更一些處理行為,例如以下不區分大小寫的金鑰和值範例:

const querystring = require('node:querystring')
const fastify = require('fastify')({
querystringParser: str => querystring.parse(str.toLowerCase())
})

exposeHeadRoutes

  • 預設值:true

為定義的每個 GET 路由自動建立同級 HEAD 路由。如果您想要自訂的 HEAD 處理常式而不停用此選項,請務必在 GET 路由之前定義它。

constraints

Fastify 的內建路由約束由 find-my-way 提供,它允許按 versionhost 約束路由。您可以透過提供帶有 find-my-way 策略的 constraints 物件,新增新的約束策略,或覆寫內建策略。您可以在 find-my-way 文件中找到有關約束策略的更多資訊。

const customVersionStrategy = {
storage: function () {
const versions = {}
return {
get: (version) => { return versions[version] || null },
set: (version, store) => { versions[version] = store }
}
},
deriveVersion: (req, ctx) => {
return req.headers['accept']
}
}

const fastify = require('fastify')({
constraints: {
version: customVersionStrategy
}
})

return503OnClosing

  • 預設值:true

在呼叫 close 伺服器方法後,傳回 503。如果為 false,則伺服器會像往常一樣路由傳入的要求。

ajv

設定 Fastify 使用的 Ajv v8 實例,而無需提供自訂實例。預設設定會在 #schema-validator 部分中說明。

const fastify = require('fastify')({
ajv: {
customOptions: {
removeAdditional: 'all' // Refer to [ajv options](https://ajv.js.org/options.html#removeadditional)
},
plugins: [
require('ajv-merge-patch'),
[require('ajv-keywords'), 'instanceof']
// Usage: [plugin, pluginOptions] - Plugin with options
// Usage: plugin - Plugin without options
]
}
})

serializerOpts

自訂序列化回應承載的預設 fast-json-stringify 實例的選項

const fastify = require('fastify')({
serializerOpts: {
rounding: 'ceil'
}
})

http2SessionTimeout

  • 預設值:72000

設定每個傳入的 HTTP/2 工作階段的預設逾時時間,單位為毫秒。工作階段將在逾時時關閉。

此選項在使用 HTTP/2 時提供優雅的「關閉」體驗是必要的。選擇較低的預設值是為了減輕阻斷服務攻擊。當伺服器位於負載平衡器之後或可以自動擴展時,可以增加此值以符合使用案例。Node 核心預設為 0

frameworkErrors

  • 預設值:null

Fastify 為最常見的使用案例提供預設的錯誤處理程序。可以使用此選項,以自訂程式碼覆寫一個或多個這些處理程序。

注意 目前僅實作 FST_ERR_BAD_URLFST_ERR_ASYNC_CONSTRAINT

const fastify = require('fastify')({
frameworkErrors: function (error, req, res) {
if (error instanceof FST_ERR_BAD_URL) {
res.code(400)
return res.send("Provided url is not valid")
} else if(error instanceof FST_ERR_ASYNC_CONSTRAINT) {
res.code(400)
return res.send("Provided header is not valid")
} else {
res.send(err)
}
}
})

clientErrorHandler

設定一個 clientErrorHandler,其監聽用戶端連線發出的 error 事件,並以 400 回應。

可以使用此選項覆寫預設的 clientErrorHandler

  • 預設值
function defaultClientErrorHandler (err, socket) {
if (err.code === 'ECONNRESET') {
return
}

const body = JSON.stringify({
error: http.STATUS_CODES['400'],
message: 'Client Error',
statusCode: 400
})
this.log.trace({ err }, 'client error')

if (socket.writable) {
socket.end([
'HTTP/1.1 400 Bad Request',
`Content-Length: ${body.length}`,
`Content-Type: application/json\r\n\r\n${body}`
].join('\r\n'))
}
}

注意 clientErrorHandler 使用原始 Socket 運作。處理程序預期會傳回格式正確的 HTTP 回應,其中包括狀態行、HTTP 標頭和訊息主體。在嘗試寫入 Socket 之前,處理程序應檢查 Socket 是否仍然可寫入,因為它可能已被銷毀。

const fastify = require('fastify')({
clientErrorHandler: function (err, socket) {
const body = JSON.stringify({
error: {
message: 'Client error',
code: '400'
}
})

// `this` is bound to fastify instance
this.log.trace({ err }, 'client error')

// the handler is responsible for generating a valid HTTP response
socket.end([
'HTTP/1.1 400 Bad Request',
`Content-Length: ${body.length}`,
`Content-Type: application/json\r\n\r\n${body}`
].join('\r\n'))
}
})

rewriteUrl

設定一個同步回呼函式,該函式必須傳回一個允許重寫 URL 的字串。當您位於變更 URL 的 Proxy 之後時,這會很有用。重寫 URL 會修改 req 物件的 url 屬性。

請注意,rewriteUrl 是在路由之前呼叫的,它沒有封裝,而且是執行個體範圍的組態。

// @param {object} req The raw Node.js HTTP request, not the `FastifyRequest` object.
// @this Fastify The root Fastify instance (not an encapsulated instance).
// @returns {string} The path that the request should be mapped to.
function rewriteUrl (req) {
if (req.url === '/hi') {
this.log.debug({ originalUrl: req.url, url: '/hello' }, 'rewrite url');
return '/hello'
} else {
return req.url;
}
}

useSemicolonDelimiter

  • 預設值:false

Fastify 使用 find-my-way,它支援以 ; 字元 (程式碼 59) 分隔路徑和查詢字串,例如 /dev;foo=bar。此決策源自[delvedor/find-my-way#76](https://github.com/delvedor/find-my-way/issues/76)。因此,此選項將支援在 ; 上進行分割的向後相容性。若要啟用在 ; 上進行分割的支援,請將 useSemicolonDelimiter 設定為 true

const fastify = require('fastify')({
useSemicolonDelimiter: true
})

fastify.get('/dev', async (request, reply) => {
// An example request such as `/dev;foo=bar`
// Will produce the following query params result `{ foo = 'bar' }`
return request.query
})

執行個體

伺服器方法

server

fastify.server:由 Fastify 工廠函式 傳回的 Node 核心 server 物件。

警告 如果使用不當,某些 Fastify 功能可能會受到干擾。建議僅將其用於附加接聽程式。

after

當目前的插件和所有在其內註冊的插件都已完成載入時會呼叫。它始終在方法 fastify.ready 之前執行。

fastify
.register((instance, opts, done) => {
console.log('Current plugin')
done()
})
.after(err => {
console.log('After current plugin')
})
.register((instance, opts, done) => {
console.log('Next plugin')
done()
})
.ready(err => {
console.log('Everything has been loaded')
})

如果呼叫 after() 時沒有函式,則會傳回 Promise

fastify.register(async (instance, opts) => {
console.log('Current plugin')
})

await fastify.after()
console.log('After current plugin')

fastify.register(async (instance, opts) => {
console.log('Next plugin')
})

await fastify.ready()

console.log('Everything has been loaded')

ready

當所有插件都已載入時呼叫的函式。如果有問題發生,則它會採用一個錯誤參數。

fastify.ready(err => {
if (err) throw err
})

如果呼叫時沒有任何引數,它會傳回 Promise

fastify.ready().then(() => {
console.log('successfully booted!')
}, (err) => {
console.log('an error happened', err)
})

listen

啟動伺服器,並在內部等待 .ready() 事件。簽章為 .listen([options][, callback])options 物件和 callback 參數都延伸了 Node.js 核心選項物件。因此,所有核心選項都可用,並具有下列額外的 Fastify 特定選項

listenTextResolver

設定伺服器成功啟動後要記錄的文字的可選解析器。可以使用此選項覆寫預設的 Server listening at [address] 記錄項目。

server.listen({ 
port: 9080,
listenTextResolver: (address) => { return `Prometheus metrics server is listening at ${address}` }
})

預設情況下,當未提供特定主機時,伺服器將接聽由 localhost 解析的位址。如果想要接聽任何可用的介面,則指定位址為 0.0.0.0 將接聽所有 IPv4 位址。下表詳細說明了當目標為 localhosthost 的可能值,以及這些 host 值將產生的結果。

主機IPv4IPv6
::*
:: + ipv6Only🚫
0.0.0.0🚫
localhost
127.0.0.1🚫
::1🚫
* 使用 `::` 作為位址將接聽所有 IPv6 位址,並且根據作業系統,也可能接聽[所有 IPv4 位址](https://node.dev.org.tw/api/net.html#serverlistenport-host-backlog-callback)。

當決定接聽所有介面時要小心;它會帶來固有的安全性風險

預設值是接聽 port: 0 (其會挑選第一個可用的開啟埠) 和 host: 'localhost'

fastify.listen((err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})

也支援指定位址

fastify.listen({ port: 3000, host: '127.0.0.1' }, (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})

如果沒有提供回呼,則會傳回 Promise

fastify.listen({ port: 3000 })
.then((address) => console.log(`server listening on ${address}`))
.catch(err => {
console.log('Error starting server:', err)
process.exit(1)
})

當部署到 Docker (可能還有其他) 容器時,建議接聽 0.0.0.0,因為它們預設不會將對應的埠公開至 localhost

fastify.listen({ port: 3000, host: '0.0.0.0' }, (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})

如果省略 port (或設定為零),則會自動選擇隨機可用的埠 (可透過 fastify.server.address().port 取得)。

listen 的預設選項為

fastify.listen({
port: 0,
host: 'localhost',
exclusive: false,
readableAll: false,
writableAll: false,
ipv6Only: false
}, (err) => {})

addresses

此方法會傳回伺服器接聽的位址陣列。如果您在呼叫 listen() 之前或在 close() 函式之後呼叫它,則會傳回空陣列。

await fastify.listen({ port: 8080 })
const addresses = fastify.addresses()
// [
// { port: 8080, family: 'IPv6', address: '::1' },
// { port: 8080, family: 'IPv4', address: '127.0.0.1' }
// ]

請注意,該陣列也包含 fastify.server.address()

routing

存取內部路由器 lookup 方法並將請求與適當處理程序匹配的方法

fastify.routing(req, res)

route

將路由新增至伺服器的方法,它也有簡寫函式,請查看這裡

hasRoute

檢查路由是否已註冊到內部路由器的方法。它預期酬載為物件。urlmethod 是必要欄位。也可以指定 constraints。如果路由已註冊,則該方法會傳回 true,否則傳回 false

const routeExists = fastify.hasRoute({
url: '/',
method: 'GET',
constraints: { version: '1.0.0' } // optional
})

if (routeExists === false) {
// add route
}

findRoute

擷取已註冊到內部路由器的路由的方法。它預期酬載為物件。urlmethod 是必要欄位。也可以指定 constraints。如果找不到路由,則該方法會傳回路由物件或 null

const route = fastify.findRoute({
url: '/artists/:artistId',
method: 'GET',
constraints: { version: '1.0.0' } // optional
})

if (route !== null) {
// perform some route checks
console.log(route.params) // `{artistId: ':artistId'}`
}

close

fastify.close(callback):呼叫此函式以關閉伺服器執行個體並執行 'onClose' 掛鉤。

呼叫 close 也會導致伺服器以 503 錯誤回應每個新的傳入請求並銷毀該請求。請參閱 return503OnClosing 旗標以變更此行為。

如果呼叫時沒有任何引數,它會傳回 Promise

fastify.close().then(() => {
console.log('successfully closed!')
}, (err) => {
console.log('an error happened', err)
})

decorate*

如果您需要裝飾 fastify 執行個體、Reply 或 Request,則此函式很有用,請查看這裡

register

Fastify 允許使用者使用插件擴充其功能。插件可以是一組路由、伺服器裝飾器或任何其他內容,請查看這裡

addHook

在 Fastify 的生命週期中新增特定掛鉤的函式,請查看這裡

prefix

將附加到路由的完整路徑。

範例

fastify.register(function (instance, opts, done) {
instance.get('/foo', function (request, reply) {
// Will log "prefix: /v1"
request.log.info('prefix: %s', instance.prefix)
reply.send({ prefix: instance.prefix })
})

instance.register(function (instance, opts, done) {
instance.get('/bar', function (request, reply) {
// Will log "prefix: /v1/v2"
request.log.info('prefix: %s', instance.prefix)
reply.send({ prefix: instance.prefix })
})

done()
}, { prefix: '/v2' })

done()
}, { prefix: '/v1' })

pluginName

目前插件的名稱。根插件稱為 'fastify'。有多種不同的方式可以定義名稱 (依序)。

  1. 如果您使用 fastify-plugin,則會使用中繼資料 name
  2. 如果匯出的插件具有 Symbol.for('fastify.display-name') 屬性,則會使用該屬性的值。範例:pluginFn[Symbol.for('fastify.display-name')] = "Custom Name"
  3. 如果您 module.exports 插件,則會使用檔案名稱。
  4. 如果您使用一般的函式宣告,則會使用函式名稱。

後援:插件的前兩行將表示插件名稱。換行符號會取代為 --。當您處理許多插件時,這將有助於識別根本原因。

警告 如果您需要處理巢狀外掛程式,由於不會建立新的作用域,因此名稱會因使用 fastify-plugin 而有所不同,因此我們沒有地方附加上下文資料。在這種情況下,外掛程式名稱將以 fastify -> plugin-A -> plugin-B 的格式表示所有相關外掛程式的啟動順序。

hasPlugin

檢查是否已註冊特定外掛程式的方法。依賴外掛程式中繼資料名稱。如果外掛程式已註冊,則傳回 true。否則,傳回 false

const fastify = require('fastify')()
fastify.register(require('@fastify/cookie'), {
secret: 'my-secret',
parseOptions: {}
})

fastify.ready(() => {
fastify.hasPlugin('@fastify/cookie') // true
})

listeningOrigin

伺服器目前正在監聽的來源。例如,基於 TCP socket 的伺服器會傳回一個類似 http://127.0.0.1:3000 的基礎位址,而 Unix socket 伺服器會傳回 socket 路徑,例如 fastify.temp.sock

log

記錄器實例,請查看這裡

version

實例的 Fastify 版本。用於外掛程式支援。有關外掛程式如何使用版本的資訊,請參閱外掛程式

inject

虛擬 HTTP 注入(用於測試目的)請參閱這裡

addHttpMethod

Fastify 預設支援 GETHEADTRACEDELETEOPTIONSPATCHPUTPOST HTTP 方法。addHttpMethod 方法允許將任何非標準 HTTP 方法新增至伺服器,這些方法是 Node.js 支援的

// Add a new HTTP method called 'MKCOL' that supports a request body
fastify.addHttpMethod('MKCOL', { hasBody: true, })

// Add a new HTTP method called 'COPY' that does not support a request body
fastify.addHttpMethod('COPY')

呼叫 addHttpMethod 之後,可以使用路由快捷方法來定義新 HTTP 方法的路由

fastify.addHttpMethod('MKCOL', { hasBody: true })
fastify.mkcol('/', (req, reply) => {
// Handle the 'MKCOL' request
})

addSchema

fastify.addSchema(schemaObj),將 JSON schema 新增至 Fastify 實例。這允許您僅使用標準 $ref 關鍵字在應用程式中的任何位置重複使用它。

若要了解更多資訊,請閱讀驗證和序列化文件。

getSchemas

fastify.getSchemas(),傳回透過 .addSchema 新增的所有 schema 的雜湊。雜湊的索引鍵是所提供 JSON Schema 的 $id

getSchema

fastify.getSchema(id),傳回使用 .addSchema 新增且與 id 相符的 JSON schema。如果找不到,則傳回 undefined

setReplySerializer

為所有路由設定回覆序列化程式。如果尚未設定 Reply.serializer(func),這將用作預設值。處理常式是完全封裝的,因此不同的外掛程式可以設定不同的錯誤處理常式。注意:僅針對狀態碼 2xx 呼叫函式參數。請查看 setErrorHandler 以取得錯誤資訊。

fastify.setReplySerializer(function (payload, statusCode){
// serialize the payload with a sync function
return `my serialized ${statusCode} content: ${payload}`
})

setValidatorCompiler

為所有路由設定 schema 驗證器編譯器。請參閱#schema-validator

setSchemaErrorFormatter

為所有路由設定 schema 錯誤格式化程式。請參閱#error-handling

setSerializerCompiler

為所有路由設定 schema 序列化程式編譯器。請參閱#schema-serializer

注意 如果設定了 setReplySerializer,則具有優先權!

validatorCompiler

此屬性可用於取得 schema 驗證器。如果未設定,它將為 null,直到伺服器啟動,然後它將是一個具有簽名 function ({ schema, method, url, httpPart }) 的函式,該函式傳回輸入的 schema,該 schema 會編譯為用於驗證資料的函式。輸入的 schema 可以存取使用 .addSchema 函式新增的所有共用 schema。

serializerCompiler

此屬性可用於取得 schema 序列化程式。如果未設定,它將為 null,直到伺服器啟動,然後它將是一個具有簽名 function ({ schema, method, url, httpPart }) 的函式,該函式傳回輸入的 schema,該 schema 會編譯為用於驗證資料的函式。輸入的 schema 可以存取使用 .addSchema 函式新增的所有共用 schema。

schemaErrorFormatter

此屬性可用於設定一個函式,以格式化在 validationCompiler 無法驗證 schema 時發生的錯誤。請參閱#error-handling

schemaController

此屬性可用於完全管理

  • bucket:應用程式的 schema 將儲存在此處
  • compilersFactory:哪個模組必須編譯 JSON schema

當您的 schema 儲存在 Fastify 未知的另一個資料結構中時,此功能會很有用。

另一個使用案例是調整所有 schema 處理。這樣做可以使用 Ajv v8 JTD 或獨立功能。若要使用 JTD 或獨立模式,請參閱 @fastify/ajv-compiler 文件

const fastify = Fastify({
schemaController: {
/**
* This factory is called whenever `fastify.register()` is called.
* It may receive as input the schemas of the parent context if some schemas have been added.
* @param {object} parentSchemas these schemas will be returned by the
* `getSchemas()` method function of the returned `bucket`.
*/
bucket: function factory (parentSchemas) {
return {
add (inputSchema) {
// This function must store the schema added by the user.
// This function is invoked when `fastify.addSchema()` is called.
},
getSchema (schema$id) {
// This function must return the raw schema requested by the `schema$id`.
// This function is invoked when `fastify.getSchema(id)` is called.
return aSchema
},
getSchemas () {
// This function must return all the schemas referenced by the routes schemas' $ref
// It must return a JSON where the property is the schema `$id` and the value is the raw JSON Schema.
const allTheSchemaStored = {
'schema$id1': schema1,
'schema$id2': schema2
}
return allTheSchemaStored
}
}
},

/**
* The compilers factory lets you fully control the validator and serializer
* in the Fastify's lifecycle, providing the encapsulation to your compilers.
*/
compilersFactory: {
/**
* This factory is called whenever a new validator instance is needed.
* It may be called whenever `fastify.register()` is called only if new schemas have been added to the
* encapsulation context.
* It may receive as input the schemas of the parent context if some schemas have been added.
* @param {object} externalSchemas these schemas will be returned by the
* `bucket.getSchemas()`. Needed to resolve the external references $ref.
* @param {object} ajvServerOption the server `ajv` options to build your compilers accordingly
*/
buildValidator: function factory (externalSchemas, ajvServerOption) {
// This factory function must return a schema validator compiler.
// See [#schema-validator](./Validation-and-Serialization.md#schema-validator) for details.
const yourAjvInstance = new Ajv(ajvServerOption.customOptions)
return function validatorCompiler ({ schema, method, url, httpPart }) {
return yourAjvInstance.compile(schema)
}
},

/**
* This factory is called whenever a new serializer instance is needed.
* It may be called whenever `fastify.register()` is called only if new schemas have been added to the
* encapsulation context.
* It may receive as input the schemas of the parent context if some schemas have been added.
* @param {object} externalSchemas these schemas will be returned by the
* `bucket.getSchemas()`. Needed to resolve the external references $ref.
* @param {object} serializerOptsServerOption the server `serializerOpts`
* options to build your compilers accordingly
*/
buildSerializer: function factory (externalSchemas, serializerOptsServerOption) {
// This factory function must return a schema serializer compiler.
// See [#schema-serializer](./Validation-and-Serialization.md#schema-serializer) for details.
return function serializerCompiler ({ schema, method, url, httpStatus, contentType }) {
return data => JSON.stringify(data)
}
}
}
}
});

setNotFoundHandler

fastify.setNotFoundHandler(handler(request, reply)):設定 404 處理常式。此呼叫會依字首封裝,因此如果將不同的 prefix 選項傳遞至 fastify.register(),則不同的外掛程式可以設定不同的找不到處理常式。該處理常式會被視為一般的路由處理常式,因此請求將會通過完整的 Fastify 生命周期。也支援 *async-await*。

您也可以為 404 處理常式註冊 preValidationpreHandler hook。

注意 使用此方法註冊的 preValidation hook 將針對 Fastify 無法辨識的路由執行,而當路由處理常式手動呼叫 reply.callNotFound 時則不會執行。在這種情況下,只會執行 preHandler。

fastify.setNotFoundHandler({
preValidation: (req, reply, done) => {
// your code
done()
},
preHandler: (req, reply, done) => {
// your code
done()
}
}, function (request, reply) {
// Default not found handler with preValidation and preHandler hooks
})

fastify.register(function (instance, options, done) {
instance.setNotFoundHandler(function (request, reply) {
// Handle not found request without preValidation and preHandler hooks
// to URLs that begin with '/v1'
})
done()
}, { prefix: '/v1' })

在註冊外掛程式之前,Fastify 會在啟動時呼叫 setNotFoundHandler 以新增預設的 404 處理常式。如果您想要增強預設 404 處理常式的行為,例如使用外掛程式,您可以在這些已註冊外掛程式的內容中呼叫不帶參數的 setNotFoundHandler fastify.setNotFoundHandler()

注意 請求物件中的某些 config 屬性在自訂找不到處理常式內會是未定義的。例如:request.routerPathrouterMethodcontext.config。此方法的設計目標是允許呼叫一般找不到路由。若要傳回每個路由自訂的 404 回應,您可以在回應本身中執行此操作。

setErrorHandler

fastify.setErrorHandler(handler(error, request, reply)):設定在發生錯誤時將會呼叫的函式。該處理常式會繫結至 Fastify 實例,並且是完全封裝的,因此不同的外掛程式可以設定不同的錯誤處理常式。也支援 *async-await*。

如果錯誤的 statusCode 小於 400,Fastify 會在呼叫錯誤處理常式之前自動將其設定為 500。

setErrorHandler不會捕獲

  • onResponse hook 中擲出的錯誤,因為回應已傳送至用戶端。請改用 onSend hook。
  • 找不到 (404) 錯誤。請改用 setNotFoundHandler
fastify.setErrorHandler(function (error, request, reply) {
// Log error
this.log.error(error)
// Send error response
reply.status(409).send({ ok: false })
})

如果未設定錯誤處理常式,則會為 Fastify 提供一個預設函式,如果未設定錯誤處理常式,則會呼叫此函式。可以使用 fastify.errorHandler 存取它,並且它會根據其 statusCode 來記錄錯誤。

var statusCode = error.statusCode
if (statusCode >= 500) {
log.error(error)
} else if (statusCode >= 400) {
log.info(error)
} else {
log.error(error)
}

setChildLoggerFactory

fastify.setChildLoggerFactory(factory(logger, bindings, opts, rawReq)):設定一個函式,該函式將在為每個請求建立子記錄器實例時呼叫,這允許修改或新增子記錄器繫結和記錄器選項,或傳回自訂子記錄器實作。

子記錄器繫結比每個記錄繫結具有效能優勢,因為它們在建立子記錄器時會由 Pino 預先序列化。

第一個參數是父記錄器實例,後面接著應傳遞至子記錄器的預設繫結和記錄器選項,最後是原始請求(不是 Fastify 請求物件)。該函式與 this 繫結,該 this 為 Fastify 實例。

例如

const fastify = require('fastify')({
childLoggerFactory: function (logger, bindings, opts, rawReq) {
// Calculate additional bindings from the request if needed
bindings.traceContext = rawReq.headers['x-cloud-trace-context']
return logger.child(bindings, opts)
}
})

該處理常式會繫結至 Fastify 實例,並且是完全封裝的,因此不同的外掛程式可以設定不同的記錄器工廠。

setGenReqId

fastify.setGenReqId(function (rawReq)) 用於設定其他 Fastify 實例的 request-id 的同步函式。它將接收原始傳入請求作為參數。在任何情況下,所提供的函式都不應擲回錯誤。

尤其是在分散式系統中,您可能需要覆寫預設的 ID 產生行為,以處理產生不同 ID 的自訂方式,以便處理不同的使用案例。例如可觀測性或網路鉤子外掛程式。

例如

const fastify = require('fastify')({
genReqId: (req) => {
return 'base'
}
})

fastify.register((instance, opts, done) => {
instance.setGenReqId((req) => {
// custom request ID for `/webhooks`
return 'webhooks-id'
})
done()
}, { prefix: '/webhooks' })

fastify.register((instance, opts, done) => {
instance.setGenReqId((req) => {
// custom request ID for `/observability`
return 'observability-id'
})
done()
}, { prefix: '/observability' })

該處理常式會繫結至 Fastify 實例,並且是完全封裝的,因此不同的外掛程式可以設定不同的請求 ID。

addConstraintStrategy

新增自訂約束策略的函式。若要註冊新的約束類型,您必須新增一個新的約束策略,該策略知道如何將值與處理常式匹配,並且知道如何從請求中取得約束值。

使用 fastify.addConstraintStrategy 方法新增自訂約束策略

const customResponseTypeStrategy = {
// strategy name for referencing in the route handler `constraints` options
name: 'accept',
// storage factory for storing routes in the find-my-way route tree
storage: function () {
let handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
// function to get the value of the constraint from each incoming request
deriveConstraint: (req, ctx) => {
return req.headers['accept']
},
// optional flag marking if handlers without constraints can match requests that have a value for this constraint
mustMatchWhenDerived: true
}

const router = Fastify();
router.addConstraintStrategy(customResponseTypeStrategy);

hasConstraintStrategy

fastify.hasConstraintStrategy(strategyName) 檢查是否已存在具有相同名稱的自訂約束策略。

printRoutes

fastify.printRoutes(): Fastify 路由器為每個 HTTP 方法建立一個路由樹。如果您在未指定 HTTP 方法的情況下呼叫 prettyPrint,它會將所有樹合併為一個並列印出來。合併後的樹並不代表內部路由器結構。請勿將其用於除錯。

請記得在 ready 呼叫內或之後呼叫它。

fastify.get('/test', () => {})
fastify.get('/test/hello', () => {})
fastify.get('/testing', () => {})
fastify.get('/testing/:param', () => {})
fastify.put('/update', () => {})

fastify.ready(() => {
console.log(fastify.printRoutes())
// └── /
// ├── test (GET)
// │ ├── /hello (GET)
// │ └── ing (GET)
// │ └── /
// │ └── :param (GET)
// └── update (PUT)
})

如果您想要列印內部路由器樹,您應該指定 method 參數。列印出的樹將代表內部路由器結構。您可以使用它進行除錯。

  console.log(fastify.printRoutes({ method: 'GET' }))
// └── /
// └── test (GET)
// ├── /hello (GET)
// └── ing (GET)
// └── /
// └── :param (GET)

console.log(fastify.printRoutes({ method: 'PUT' }))
// └── /
// └── update (PUT)

fastify.printRoutes({ commonPrefix: false }) 將列印壓縮樹。當您有大量具有共同前綴的路由時,這可能很有用。它並不代表內部路由器結構。請勿將其用於除錯。

  console.log(fastify.printRoutes({ commonPrefix: false }))
// ├── /test (GET)
// │ ├── /hello (GET)
// │ └── ing (GET)
// │ └── /:param (GET)
// └── /update (PUT)

fastify.printRoutes({ includeMeta: (true | []) }) 將顯示每個顯示路由的 route.store 物件中的屬性。這可以是金鑰的 array (例如 ['onRequest', Symbol('key')]),或 true 來顯示所有屬性。一個簡寫選項,fastify.printRoutes({ includeHooks: true }) 將包含所有 hook

  fastify.get('/test', () => {})
fastify.get('/test/hello', () => {})

const onTimeout = () => {}

fastify.addHook('onRequest', () => {})
fastify.addHook('onTimeout', onTimeout)

console.log(fastify.printRoutes({ includeHooks: true, includeMeta: ['errorHandler'] }))
// └── /
// └── test (GET)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// • (errorHandler) "defaultErrorHandler()"
// test (HEAD)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// • (onSend) ["headRouteOnSendHandler()"]
// • (errorHandler) "defaultErrorHandler()"
// └── /hello (GET)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// • (errorHandler) "defaultErrorHandler()"
// /hello (HEAD)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// • (onSend) ["headRouteOnSendHandler()"]
// • (errorHandler) "defaultErrorHandler()"

console.log(fastify.printRoutes({ includeHooks: true }))
// └── /
// └── test (GET)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// test (HEAD)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// • (onSend) ["headRouteOnSendHandler()"]
// └── /hello (GET)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// /hello (HEAD)
// • (onTimeout) ["onTimeout()"]
// • (onRequest) ["anonymous()"]
// • (onSend) ["headRouteOnSendHandler()"]

printPlugins

fastify.printPlugins():列印 avvio 使用的內部外掛程式樹的表示法,對於除錯請求順序問題很有用。

請記得在 ready 呼叫內或之後呼叫它。

fastify.register(async function foo (instance) {
instance.register(async function bar () {})
})
fastify.register(async function baz () {})

fastify.ready(() => {
console.error(fastify.printPlugins())
// will output the following to stderr:
// └── root
// ├── foo
// │ └── bar
// └── baz
})

addContentTypeParser

fastify.addContentTypeParser(content-type, options, parser) 用於為指定的內容類型傳遞自訂剖析器。對於為自訂內容類型新增剖析器很有用,例如 text/json, application/vnd.oasis.opendocument.textcontent-type 可以是字串、字串陣列或 RegExp。

// The two arguments passed to getDefaultJsonParser are for ProtoType poisoning
// and Constructor Poisoning configuration respectively. The possible values are
// 'ignore', 'remove', 'error'. ignore skips all validations and it is similar
// to calling JSON.parse() directly. See the
// [`secure-json-parse` documentation](https://github.com/fastify/secure-json-parse#api) for more information.

fastify.addContentTypeParser('text/json', { asString: true }, fastify.getDefaultJsonParser('ignore', 'ignore'))

hasContentTypeParser

fastify.hasContentTypeParser(contentType) 用於檢查目前上下文中是否存在指定內容類型的內容類型剖析器。

fastify.hasContentTypeParser('text/json')

fastify.hasContentTypeParser(/^.+\/json$/)

removeContentTypeParser

fastify.removeContentTypeParser(contentType) 用於移除目前上下文中的內容類型剖析器。此方法允許例如移除 application/jsontext/plain 的兩個內建剖析器。

fastify.removeContentTypeParser('application/json')

fastify.removeContentTypeParser(['application/json', 'text/plain'])

removeAllContentTypeParsers

fastify.removeAllContentTypeParsers() 方法允許移除目前上下文中的所有內容類型剖析器。此方法的一個用例是實作 catch-all 內容類型剖析器。在使用 fastify.addContentTypeParser() 新增此剖析器之前,可以呼叫 removeAllContentTypeParsers 方法。

有關不同內容類型剖析器 API 用法的更多詳細資訊,請參閱此處

getDefaultJsonParser

fastify.getDefaultJsonParser(onProtoPoisoning, onConstructorPoisoning) 接受兩個參數。第一個參數是 ProtoType poisoning 配置,第二個參數是 constructor poisoning 配置。有關更多資訊,請參閱 secure-json-parse 文件

defaultTextParser

fastify.defaultTextParser() 可用於將內容剖析為純文字。

fastify.addContentTypeParser('text/json', { asString: true }, fastify.defaultTextParser)

errorHandler

fastify.errorHandler 可用於使用 fastify 的預設錯誤處理常式來處理錯誤。

fastify.get('/', {
errorHandler: (error, request, reply) => {
if (error.code === 'SOMETHING_SPECIFIC') {
reply.send({ custom: 'response' })
return
}

fastify.errorHandler(error, request, response)
}
}, handler)

childLoggerFactory

fastify.childLoggerFactory 傳回 Fastify 實例的自訂記錄器工廠函式。有關更多資訊,請參閱childLoggerFactory 配置選項

Symbol.asyncDispose

fastify[Symbol.asyncDispose] 是一個符號,可用於定義一個非同步函式,該函式會在 Fastify 實例關閉時呼叫。

它通常與 using TypeScript 關鍵字一起使用,以確保在 Fastify 實例關閉時清理資源。

這在短暫的流程或單元測試中完美結合,您必須在從函式內傳回後關閉所有 Fastify 資源。

test('Uses app and closes it afterwards', async () => {
await using app = fastify();
// do something with app.
})

在上面的範例中,Fastify 在測試結束後會自動關閉。

深入了解 ECMAScript 顯式資源管理和 TypeScript 5.2 中引入的 using 關鍵字

initialConfig

fastify.initialConfig:公開一個凍結的唯讀物件,該物件註冊使用者傳遞給 Fastify 實例的初始選項。

目前可以公開的屬性為

  • connectionTimeout
  • keepAliveTimeout
  • bodyLimit
  • caseSensitive
  • allowUnsafeRegex
  • http2
  • https (如果明確傳遞,它將傳回 false/true{ allowHTTP1: true/false })
  • ignoreTrailingSlash
  • disableRequestLogging
  • maxParamLength
  • onProtoPoisoning
  • onConstructorPoisoning
  • pluginTimeout
  • requestIdHeader
  • requestIdLogLabel
  • http2SessionTimeout
  • useSemicolonDelimiter
const { readFileSync } = require('node:fs')
const Fastify = require('fastify')

const fastify = Fastify({
https: {
allowHTTP1: true,
key: readFileSync('./fastify.key'),
cert: readFileSync('./fastify.cert')
},
logger: { level: 'trace'},
ignoreTrailingSlash: true,
maxParamLength: 200,
caseSensitive: true,
trustProxy: '127.0.0.1,192.168.1.1/24',
})

console.log(fastify.initialConfig)
/*
will log :
{
caseSensitive: true,
https: { allowHTTP1: true },
ignoreTrailingSlash: true,
maxParamLength: 200
}
*/

fastify.register(async (instance, opts) => {
instance.get('/', async (request, reply) => {
return instance.initialConfig
/*
will return :
{
caseSensitive: true,
https: { allowHTTP1: true },
ignoreTrailingSlash: true,
maxParamLength: 200
}
*/
})

instance.get('/error', async (request, reply) => {
// will throw an error because initialConfig is read-only
// and can not be modified
instance.initialConfig.https.allowHTTP1 = false

return instance.initialConfig
})
})

// Start listening.
fastify.listen({ port: 3000 }, (err) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})