node-fastify 5.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/.borp.yaml +3 -0
  2. package/.markdownlint-cli2.yaml +22 -0
  3. package/.prettierignore +1 -0
  4. package/GOVERNANCE.md +4 -0
  5. package/LICENSE +21 -0
  6. package/PROJECT_CHARTER.md +126 -0
  7. package/README.md +423 -0
  8. package/SECURITY.md +220 -0
  9. package/SPONSORS.md +24 -0
  10. package/build/build-error-serializer.js +35 -0
  11. package/build/build-validation.js +169 -0
  12. package/build/sync-version.js +11 -0
  13. package/docs/Guides/Benchmarking.md +60 -0
  14. package/docs/Guides/Database.md +321 -0
  15. package/docs/Guides/Delay-Accepting-Requests.md +608 -0
  16. package/docs/Guides/Detecting-When-Clients-Abort.md +172 -0
  17. package/docs/Guides/Ecosystem.md +726 -0
  18. package/docs/Guides/Fluent-Schema.md +127 -0
  19. package/docs/Guides/Getting-Started.md +620 -0
  20. package/docs/Guides/Index.md +43 -0
  21. package/docs/Guides/Migration-Guide-V3.md +287 -0
  22. package/docs/Guides/Migration-Guide-V4.md +267 -0
  23. package/docs/Guides/Migration-Guide-V5.md +727 -0
  24. package/docs/Guides/Plugins-Guide.md +520 -0
  25. package/docs/Guides/Prototype-Poisoning.md +383 -0
  26. package/docs/Guides/Recommendations.md +378 -0
  27. package/docs/Guides/Serverless.md +604 -0
  28. package/docs/Guides/Style-Guide.md +246 -0
  29. package/docs/Guides/Testing.md +481 -0
  30. package/docs/Guides/Write-Plugin.md +103 -0
  31. package/docs/Guides/Write-Type-Provider.md +34 -0
  32. package/docs/Reference/ContentTypeParser.md +271 -0
  33. package/docs/Reference/Decorators.md +436 -0
  34. package/docs/Reference/Encapsulation.md +194 -0
  35. package/docs/Reference/Errors.md +377 -0
  36. package/docs/Reference/HTTP2.md +94 -0
  37. package/docs/Reference/Hooks.md +958 -0
  38. package/docs/Reference/Index.md +73 -0
  39. package/docs/Reference/LTS.md +86 -0
  40. package/docs/Reference/Lifecycle.md +99 -0
  41. package/docs/Reference/Logging.md +268 -0
  42. package/docs/Reference/Middleware.md +79 -0
  43. package/docs/Reference/Plugins.md +245 -0
  44. package/docs/Reference/Principles.md +73 -0
  45. package/docs/Reference/Reply.md +1001 -0
  46. package/docs/Reference/Request.md +295 -0
  47. package/docs/Reference/Routes.md +802 -0
  48. package/docs/Reference/Server.md +2389 -0
  49. package/docs/Reference/Type-Providers.md +256 -0
  50. package/docs/Reference/TypeScript.md +1729 -0
  51. package/docs/Reference/Validation-and-Serialization.md +1130 -0
  52. package/docs/Reference/Warnings.md +58 -0
  53. package/docs/index.md +24 -0
  54. package/docs/resources/encapsulation_context.drawio +1 -0
  55. package/docs/resources/encapsulation_context.svg +3 -0
  56. package/eslint.config.js +35 -0
  57. package/examples/asyncawait.js +38 -0
  58. package/examples/benchmark/body.json +3 -0
  59. package/examples/benchmark/hooks-benchmark-async-await.js +44 -0
  60. package/examples/benchmark/hooks-benchmark.js +52 -0
  61. package/examples/benchmark/parser.js +47 -0
  62. package/examples/benchmark/simple.js +30 -0
  63. package/examples/benchmark/webstream.js +27 -0
  64. package/examples/hooks.js +91 -0
  65. package/examples/http2.js +39 -0
  66. package/examples/https.js +38 -0
  67. package/examples/parser.js +53 -0
  68. package/examples/plugin.js +12 -0
  69. package/examples/route-prefix.js +38 -0
  70. package/examples/shared-schema.js +38 -0
  71. package/examples/simple-stream.js +20 -0
  72. package/examples/simple.js +32 -0
  73. package/examples/simple.mjs +27 -0
  74. package/examples/typescript-server.ts +79 -0
  75. package/examples/use-plugin.js +29 -0
  76. package/fastify.d.ts +253 -0
  77. package/fastify.js +985 -0
  78. package/integration/server.js +29 -0
  79. package/integration/test.sh +23 -0
  80. package/lib/config-validator.js +1266 -0
  81. package/lib/content-type-parser.js +413 -0
  82. package/lib/content-type.js +160 -0
  83. package/lib/context.js +98 -0
  84. package/lib/decorate.js +152 -0
  85. package/lib/error-handler.js +173 -0
  86. package/lib/error-serializer.js +134 -0
  87. package/lib/error-status.js +14 -0
  88. package/lib/errors.js +516 -0
  89. package/lib/four-oh-four.js +190 -0
  90. package/lib/handle-request.js +195 -0
  91. package/lib/head-route.js +45 -0
  92. package/lib/hooks.js +429 -0
  93. package/lib/initial-config-validation.js +37 -0
  94. package/lib/logger-factory.js +136 -0
  95. package/lib/logger-pino.js +68 -0
  96. package/lib/noop-set.js +10 -0
  97. package/lib/plugin-override.js +90 -0
  98. package/lib/plugin-utils.js +169 -0
  99. package/lib/promise.js +23 -0
  100. package/lib/reply.js +1030 -0
  101. package/lib/req-id-gen-factory.js +52 -0
  102. package/lib/request.js +391 -0
  103. package/lib/route.js +686 -0
  104. package/lib/schema-controller.js +164 -0
  105. package/lib/schemas.js +207 -0
  106. package/lib/server.js +441 -0
  107. package/lib/symbols.js +71 -0
  108. package/lib/validation.js +280 -0
  109. package/lib/warnings.js +57 -0
  110. package/lib/wrap-thenable.js +84 -0
  111. package/package.json +225 -0
  112. package/scripts/validate-ecosystem-links.js +179 -0
  113. package/test/404s.test.js +2035 -0
  114. package/test/500s.test.js +422 -0
  115. package/test/allow-unsafe-regex.test.js +92 -0
  116. package/test/als.test.js +65 -0
  117. package/test/async-await.test.js +705 -0
  118. package/test/async-dispose.test.js +20 -0
  119. package/test/async_hooks.test.js +52 -0
  120. package/test/body-limit.test.js +224 -0
  121. package/test/buffer.test.js +74 -0
  122. package/test/build/error-serializer.test.js +36 -0
  123. package/test/build/version.test.js +14 -0
  124. package/test/build-certificate.js +109 -0
  125. package/test/bundler/README.md +29 -0
  126. package/test/bundler/esbuild/bundler-test.js +32 -0
  127. package/test/bundler/esbuild/package.json +10 -0
  128. package/test/bundler/esbuild/src/fail-plugin-version.js +14 -0
  129. package/test/bundler/esbuild/src/index.js +9 -0
  130. package/test/bundler/webpack/bundler-test.js +32 -0
  131. package/test/bundler/webpack/package.json +11 -0
  132. package/test/bundler/webpack/src/fail-plugin-version.js +14 -0
  133. package/test/bundler/webpack/src/index.js +9 -0
  134. package/test/bundler/webpack/webpack.config.js +15 -0
  135. package/test/case-insensitive.test.js +102 -0
  136. package/test/chainable.test.js +40 -0
  137. package/test/child-logger-factory.test.js +128 -0
  138. package/test/client-timeout.test.js +38 -0
  139. package/test/close-pipelining.test.js +78 -0
  140. package/test/close.test.js +706 -0
  141. package/test/conditional-pino.test.js +47 -0
  142. package/test/connection-timeout.test.js +42 -0
  143. package/test/constrained-routes.test.js +1138 -0
  144. package/test/content-length.test.js +174 -0
  145. package/test/content-parser.test.js +739 -0
  146. package/test/content-type.test.js +181 -0
  147. package/test/context-config.test.js +164 -0
  148. package/test/custom-http-server.test.js +118 -0
  149. package/test/custom-parser-async.test.js +59 -0
  150. package/test/custom-parser.0.test.js +701 -0
  151. package/test/custom-parser.1.test.js +266 -0
  152. package/test/custom-parser.2.test.js +91 -0
  153. package/test/custom-parser.3.test.js +208 -0
  154. package/test/custom-parser.4.test.js +218 -0
  155. package/test/custom-parser.5.test.js +130 -0
  156. package/test/custom-querystring-parser.test.js +129 -0
  157. package/test/decorator.test.js +1330 -0
  158. package/test/delete.test.js +344 -0
  159. package/test/diagnostics-channel/404.test.js +49 -0
  160. package/test/diagnostics-channel/async-delay-request.test.js +65 -0
  161. package/test/diagnostics-channel/async-request.test.js +64 -0
  162. package/test/diagnostics-channel/error-before-handler.test.js +35 -0
  163. package/test/diagnostics-channel/error-request.test.js +53 -0
  164. package/test/diagnostics-channel/error-status.test.js +123 -0
  165. package/test/diagnostics-channel/init.test.js +50 -0
  166. package/test/diagnostics-channel/sync-delay-request.test.js +49 -0
  167. package/test/diagnostics-channel/sync-request-reply.test.js +51 -0
  168. package/test/diagnostics-channel/sync-request.test.js +54 -0
  169. package/test/encapsulated-child-logger-factory.test.js +69 -0
  170. package/test/encapsulated-error-handler.test.js +237 -0
  171. package/test/esm/errorCodes.test.mjs +10 -0
  172. package/test/esm/esm.test.mjs +13 -0
  173. package/test/esm/index.test.js +8 -0
  174. package/test/esm/named-exports.mjs +14 -0
  175. package/test/esm/other.mjs +8 -0
  176. package/test/esm/plugin.mjs +8 -0
  177. package/test/fastify-instance.test.js +300 -0
  178. package/test/find-route.test.js +152 -0
  179. package/test/fluent-schema.test.js +209 -0
  180. package/test/genReqId.test.js +426 -0
  181. package/test/handler-context.test.js +45 -0
  182. package/test/handler-timeout.test.js +367 -0
  183. package/test/has-route.test.js +88 -0
  184. package/test/header-overflow.test.js +55 -0
  185. package/test/helper.js +496 -0
  186. package/test/hooks-async.test.js +1099 -0
  187. package/test/hooks.on-listen.test.js +1162 -0
  188. package/test/hooks.on-ready.test.js +421 -0
  189. package/test/hooks.test.js +3578 -0
  190. package/test/http-methods/copy.test.js +35 -0
  191. package/test/http-methods/custom-http-methods.test.js +114 -0
  192. package/test/http-methods/get.test.js +412 -0
  193. package/test/http-methods/head.test.js +263 -0
  194. package/test/http-methods/lock.test.js +108 -0
  195. package/test/http-methods/mkcalendar.test.js +143 -0
  196. package/test/http-methods/mkcol.test.js +35 -0
  197. package/test/http-methods/move.test.js +42 -0
  198. package/test/http-methods/propfind.test.js +136 -0
  199. package/test/http-methods/proppatch.test.js +105 -0
  200. package/test/http-methods/report.test.js +142 -0
  201. package/test/http-methods/search.test.js +233 -0
  202. package/test/http-methods/trace.test.js +21 -0
  203. package/test/http-methods/unlock.test.js +38 -0
  204. package/test/http2/closing.test.js +270 -0
  205. package/test/http2/constraint.test.js +109 -0
  206. package/test/http2/head.test.js +34 -0
  207. package/test/http2/plain.test.js +68 -0
  208. package/test/http2/secure-with-fallback.test.js +113 -0
  209. package/test/http2/secure.test.js +67 -0
  210. package/test/http2/unknown-http-method.test.js +34 -0
  211. package/test/https/custom-https-server.test.js +58 -0
  212. package/test/https/https.test.js +136 -0
  213. package/test/imports.test.js +17 -0
  214. package/test/inject.test.js +502 -0
  215. package/test/input-validation.js +335 -0
  216. package/test/internals/all.test.js +38 -0
  217. package/test/internals/content-type-parser.test.js +111 -0
  218. package/test/internals/context.test.js +31 -0
  219. package/test/internals/decorator.test.js +156 -0
  220. package/test/internals/errors.test.js +982 -0
  221. package/test/internals/handle-request.test.js +270 -0
  222. package/test/internals/hook-runner.test.js +449 -0
  223. package/test/internals/hooks.test.js +96 -0
  224. package/test/internals/initial-config.test.js +383 -0
  225. package/test/internals/logger.test.js +163 -0
  226. package/test/internals/plugin.test.js +170 -0
  227. package/test/internals/promise.test.js +63 -0
  228. package/test/internals/reply-serialize.test.js +714 -0
  229. package/test/internals/reply.test.js +1920 -0
  230. package/test/internals/req-id-gen-factory.test.js +133 -0
  231. package/test/internals/request-validate.test.js +1402 -0
  232. package/test/internals/request.test.js +506 -0
  233. package/test/internals/schema-controller-perf.test.js +40 -0
  234. package/test/internals/server.test.js +91 -0
  235. package/test/internals/validation.test.js +352 -0
  236. package/test/issue-4959.test.js +118 -0
  237. package/test/keep-alive-timeout.test.js +42 -0
  238. package/test/listen.1.test.js +154 -0
  239. package/test/listen.2.test.js +113 -0
  240. package/test/listen.3.test.js +83 -0
  241. package/test/listen.4.test.js +168 -0
  242. package/test/listen.5.test.js +122 -0
  243. package/test/logger/instantiation.test.js +341 -0
  244. package/test/logger/logger-test-utils.js +47 -0
  245. package/test/logger/logging.test.js +460 -0
  246. package/test/logger/options.test.js +579 -0
  247. package/test/logger/request.test.js +292 -0
  248. package/test/logger/response.test.js +183 -0
  249. package/test/logger/tap-parallel-not-ok +0 -0
  250. package/test/max-requests-per-socket.test.js +113 -0
  251. package/test/middleware.test.js +37 -0
  252. package/test/noop-set.test.js +19 -0
  253. package/test/nullable-validation.test.js +187 -0
  254. package/test/options.error-handler.test.js +5 -0
  255. package/test/options.test.js +5 -0
  256. package/test/output-validation.test.js +140 -0
  257. package/test/patch.error-handler.test.js +5 -0
  258. package/test/patch.test.js +5 -0
  259. package/test/plugin.1.test.js +230 -0
  260. package/test/plugin.2.test.js +314 -0
  261. package/test/plugin.3.test.js +287 -0
  262. package/test/plugin.4.test.js +504 -0
  263. package/test/plugin.helper.js +8 -0
  264. package/test/plugin.name.display.js +10 -0
  265. package/test/post-empty-body.test.js +38 -0
  266. package/test/pretty-print.test.js +366 -0
  267. package/test/promises.test.js +125 -0
  268. package/test/proto-poisoning.test.js +145 -0
  269. package/test/put.error-handler.test.js +5 -0
  270. package/test/put.test.js +5 -0
  271. package/test/register.test.js +184 -0
  272. package/test/reply-code.test.js +148 -0
  273. package/test/reply-early-hints.test.js +100 -0
  274. package/test/reply-error.test.js +815 -0
  275. package/test/reply-trailers.test.js +445 -0
  276. package/test/reply-web-stream-locked.test.js +37 -0
  277. package/test/request-error.test.js +624 -0
  278. package/test/request-header-host.test.js +339 -0
  279. package/test/request-id.test.js +118 -0
  280. package/test/request-timeout.test.js +53 -0
  281. package/test/route-hooks.test.js +635 -0
  282. package/test/route-prefix.test.js +904 -0
  283. package/test/route-shorthand.test.js +48 -0
  284. package/test/route.1.test.js +259 -0
  285. package/test/route.2.test.js +100 -0
  286. package/test/route.3.test.js +213 -0
  287. package/test/route.4.test.js +127 -0
  288. package/test/route.5.test.js +211 -0
  289. package/test/route.6.test.js +306 -0
  290. package/test/route.7.test.js +406 -0
  291. package/test/route.8.test.js +225 -0
  292. package/test/router-options.test.js +1108 -0
  293. package/test/same-shape.test.js +124 -0
  294. package/test/schema-examples.test.js +661 -0
  295. package/test/schema-feature.test.js +2198 -0
  296. package/test/schema-serialization.test.js +1171 -0
  297. package/test/schema-special-usage.test.js +1348 -0
  298. package/test/schema-validation.test.js +1572 -0
  299. package/test/scripts/validate-ecosystem-links.test.js +339 -0
  300. package/test/serialize-response.test.js +186 -0
  301. package/test/server.test.js +347 -0
  302. package/test/set-error-handler.test.js +69 -0
  303. package/test/skip-reply-send.test.js +317 -0
  304. package/test/stream-serializers.test.js +40 -0
  305. package/test/stream.1.test.js +94 -0
  306. package/test/stream.2.test.js +129 -0
  307. package/test/stream.3.test.js +198 -0
  308. package/test/stream.4.test.js +176 -0
  309. package/test/stream.5.test.js +188 -0
  310. package/test/sync-routes.test.js +32 -0
  311. package/test/throw.test.js +359 -0
  312. package/test/toolkit.js +63 -0
  313. package/test/trust-proxy.test.js +162 -0
  314. package/test/type-provider.test.js +22 -0
  315. package/test/types/content-type-parser.test-d.ts +72 -0
  316. package/test/types/decorate-request-reply.test-d.ts +18 -0
  317. package/test/types/dummy-plugin.ts +9 -0
  318. package/test/types/errors.test-d.ts +90 -0
  319. package/test/types/fastify.test-d.ts +352 -0
  320. package/test/types/hooks.test-d.ts +550 -0
  321. package/test/types/import.ts +2 -0
  322. package/test/types/instance.test-d.ts +588 -0
  323. package/test/types/logger.test-d.ts +277 -0
  324. package/test/types/plugin.test-d.ts +97 -0
  325. package/test/types/register.test-d.ts +237 -0
  326. package/test/types/reply.test-d.ts +254 -0
  327. package/test/types/request.test-d.ts +188 -0
  328. package/test/types/route.test-d.ts +553 -0
  329. package/test/types/schema.test-d.ts +135 -0
  330. package/test/types/serverFactory.test-d.ts +37 -0
  331. package/test/types/type-provider.test-d.ts +1213 -0
  332. package/test/types/using.test-d.ts +17 -0
  333. package/test/upgrade.test.js +52 -0
  334. package/test/url-rewriting.test.js +122 -0
  335. package/test/use-semicolon-delimiter.test.js +168 -0
  336. package/test/validation-error-handling.test.js +900 -0
  337. package/test/versioned-routes.test.js +603 -0
  338. package/test/web-api.test.js +616 -0
  339. package/test/wrap-thenable.test.js +30 -0
  340. package/types/content-type-parser.d.ts +75 -0
  341. package/types/context.d.ts +22 -0
  342. package/types/errors.d.ts +92 -0
  343. package/types/hooks.d.ts +875 -0
  344. package/types/instance.d.ts +609 -0
  345. package/types/logger.d.ts +107 -0
  346. package/types/plugin.d.ts +44 -0
  347. package/types/register.d.ts +42 -0
  348. package/types/reply.d.ts +81 -0
  349. package/types/request.d.ts +95 -0
  350. package/types/route.d.ts +199 -0
  351. package/types/schema.d.ts +61 -0
  352. package/types/server-factory.d.ts +19 -0
  353. package/types/type-provider.d.ts +130 -0
  354. package/types/utils.d.ts +98 -0
@@ -0,0 +1,802 @@
1
+ <h1 align="center">Fastify</h1>
2
+
3
+ ## Routes
4
+
5
+ The route methods configure the endpoints of the application. Routes can be
6
+ declared using the shorthand method or the full declaration.
7
+
8
+ - [Full declaration](#full-declaration)
9
+ - [Routes options](#routes-options)
10
+ - [Shorthand declaration](#shorthand-declaration)
11
+ - [Url building](#url-building)
12
+ - [Async Await](#async-await)
13
+ - [Promise resolution](#promise-resolution)
14
+ - [Route Prefixing](#route-prefixing)
15
+ - [Handling of / route inside prefixed
16
+ plugins](#handling-of--route-inside-prefixed-plugins)
17
+ - [Custom Log Level](#custom-log-level)
18
+ - [Custom Log Serializer](#custom-log-serializer)
19
+ - [Config](#config)
20
+ - [Constraints](#constraints)
21
+ - [Version Constraints](#version-constraints)
22
+ - [Host Constraints](#host-constraints)
23
+
24
+ ### Full declaration
25
+ <a id="full-declaration"></a>
26
+
27
+ ```js
28
+ fastify.route(options)
29
+ ```
30
+
31
+ ### Routes options
32
+ <a id="options"></a>
33
+
34
+ * `method`: currently it supports `GET`, `HEAD`, `TRACE`, `DELETE`,
35
+ `OPTIONS`, `PATCH`, `PUT` and `POST`. To accept more methods,
36
+ the [`addHttpMethod`](./Server.md#addHttpMethod) must be used.
37
+ It could also be an array of methods.
38
+ * `url`: the path of the URL to match this route (alias: `path`).
39
+ * `schema`: an object containing the schemas for the request and response. They
40
+ need to be in [JSON Schema](https://json-schema.org/) format, check
41
+ [here](./Validation-and-Serialization.md) for more info.
42
+
43
+ * `body`: validates the body of the request if it is a POST, PUT, PATCH,
44
+ TRACE, SEARCH, PROPFIND, PROPPATCH or LOCK method.
45
+ * `querystring` or `query`: validates the querystring. This can be a complete
46
+ JSON Schema object, with the property `type` of `object` and `properties`
47
+ object of parameters, or simply the values of what would be contained in the
48
+ `properties` object as shown below.
49
+ * `params`: validates the params.
50
+ * `response`: filter and generate a schema for the response, setting a schema
51
+ allows us to have 10-20% more throughput.
52
+ * `exposeHeadRoute`: creates a sibling `HEAD` route for any `GET` routes.
53
+ Defaults to the value of [`exposeHeadRoutes`](./Server.md#exposeHeadRoutes)
54
+ instance option. If you want a custom `HEAD` handler without disabling this
55
+ option, make sure to define it before the `GET` route.
56
+ * `attachValidation`: attach `validationError` to request, if there is a schema
57
+ validation error, instead of sending the error to the error handler. The
58
+ default [error format](https://ajv.js.org/api.html#error-objects) is the Ajv
59
+ one.
60
+ * `onRequest(request, reply, done)`: a [function](./Hooks.md#onrequest) called
61
+ as soon as a request is received, it could also be an array of functions.
62
+ * `preParsing(request, reply, payload, done)`: a
63
+ [function](./Hooks.md#preparsing) called before parsing the request, it could
64
+ also be an array of functions.
65
+ * `preValidation(request, reply, done)`: a [function](./Hooks.md#prevalidation)
66
+ called after the shared `preValidation` hooks, useful if you need to perform
67
+ authentication at route level for example, it could also be an array of
68
+ functions.
69
+ * `preHandler(request, reply, done)`: a [function](./Hooks.md#prehandler) called
70
+ just before the request handler, it could also be an array of functions.
71
+ * `preSerialization(request, reply, payload, done)`: a
72
+ [function](./Hooks.md#preserialization) called just before the serialization,
73
+ it could also be an array of functions.
74
+ * `onSend(request, reply, payload, done)`: a [function](./Hooks.md#route-hooks)
75
+ called right before a response is sent, it could also be an array of
76
+ functions.
77
+ * `onResponse(request, reply, done)`: a [function](./Hooks.md#onresponse) called
78
+ when a response has been sent, so you will not be able to send more data to
79
+ the client. It could also be an array of functions.
80
+ * `onTimeout(request, reply, done)`: a [function](./Hooks.md#ontimeout) called
81
+ when a request is timed out and the HTTP socket has been hung up.
82
+ * `onError(request, reply, error, done)`: a [function](./Hooks.md#onerror)
83
+ called when an Error is thrown or sent to the client by the route handler.
84
+ * `handler(request, reply)`: the function that will handle this request. The
85
+ [Fastify server](./Server.md) will be bound to `this` when the handler is
86
+ called. Note: using an arrow function will break the binding of `this`.
87
+ * `errorHandler(error, request, reply)`: a custom error handler for the scope of
88
+ the request. Overrides the default error global handler, and anything set by
89
+ [`setErrorHandler`](./Server.md#seterrorhandler), for requests to the route.
90
+ To access the default handler, you can access `instance.errorHandler`. Note
91
+ that this will point to fastify's default `errorHandler` only if a plugin
92
+ hasn't overridden it already.
93
+ * `childLoggerFactory(logger, binding, opts, rawReq)`: a custom factory function
94
+ that will be called to produce a child logger instance for every request.
95
+ See [`childLoggerFactory`](./Server.md#childloggerfactory) for more info.
96
+ Overrides the default logger factory, and anything set by
97
+ [`setChildLoggerFactory`](./Server.md#setchildloggerfactory), for requests to
98
+ the route. To access the default factory, you can access
99
+ `instance.childLoggerFactory`. Note that this will point to Fastify's default
100
+ `childLoggerFactory` only if a plugin hasn't overridden it already.
101
+ * `validatorCompiler({ schema, method, url, httpPart })`: function that builds
102
+ schemas for request validations. See the [Validation and
103
+ Serialization](./Validation-and-Serialization.md#schema-validator)
104
+ documentation.
105
+ * `serializerCompiler({ { schema, method, url, httpStatus, contentType } })`:
106
+ function that builds schemas for response serialization. See the [Validation and
107
+ Serialization](./Validation-and-Serialization.md#schema-serializer)
108
+ documentation.
109
+ * `schemaErrorFormatter(errors, dataVar)`: function that formats the errors from
110
+ the validation compiler. See the [Validation and
111
+ Serialization](./Validation-and-Serialization.md#error-handling)
112
+ documentation. Overrides the global schema error formatter handler, and
113
+ anything set by `setSchemaErrorFormatter`, for requests to the route.
114
+ * `bodyLimit`: prevents the default JSON body parser from parsing request bodies
115
+ larger than this number of bytes. Must be an integer. You may also set this
116
+ option globally when first creating the Fastify instance with
117
+ `fastify(options)`. Defaults to `1048576` (1 MiB).
118
+ * `handlerTimeout`: maximum number of milliseconds for the route's full
119
+ lifecycle. Overrides the server-level
120
+ [`handlerTimeout`](./Server.md#factory-handler-timeout). Must be a positive
121
+ integer. When the timeout fires, `request.signal` is aborted and a 503 error
122
+ is sent through the error handler (which can be customized per-route).
123
+ * `logLevel`: set log level for this route. See below.
124
+ * `logSerializers`: set serializers to log for this route.
125
+ * `config`: object used to store custom configuration.
126
+ * `version`: a [semver](https://semver.org/) compatible string that defined the
127
+ version of the endpoint. [Example](#version-constraints).
128
+ * `constraints`: defines route restrictions based on request properties or
129
+ values, enabling customized matching using
130
+ [find-my-way](https://github.com/delvedor/find-my-way) constraints. Includes
131
+ built-in `version` and `host` constraints, with support for custom constraint
132
+ strategies.
133
+ * `prefixTrailingSlash`: string used to determine how to handle passing `/` as a
134
+ route with a prefix.
135
+ * `both` (default): Will register both `/prefix` and `/prefix/`.
136
+ * `slash`: Will register only `/prefix/`.
137
+ * `no-slash`: Will register only `/prefix`.
138
+
139
+ Note: this option does not override `ignoreTrailingSlash` in
140
+ [Server](./Server.md) configuration.
141
+
142
+ * `request` is defined in [Request](./Request.md).
143
+
144
+ * `reply` is defined in [Reply](./Reply.md).
145
+
146
+ > ℹ️ Note:
147
+ > The documentation for `onRequest`, `preParsing`, `preValidation`,
148
+ > `preHandler`, `preSerialization`, `onSend`, and `onResponse` is detailed in
149
+ > [Hooks](./Hooks.md). To send a response before the request is handled by the
150
+ > `handler`, see [Respond to a request from
151
+ > a hook](./Hooks.md#respond-to-a-request-from-a-hook).
152
+
153
+ Example:
154
+ ```js
155
+ fastify.route({
156
+ method: 'GET',
157
+ url: '/',
158
+ schema: {
159
+ querystring: {
160
+ type: 'object',
161
+ properties: {
162
+ name: { type: 'string' },
163
+ excitement: { type: 'integer' }
164
+ }
165
+ },
166
+ response: {
167
+ 200: {
168
+ type: 'object',
169
+ properties: {
170
+ hello: { type: 'string' }
171
+ }
172
+ }
173
+ }
174
+ },
175
+ handler: function (request, reply) {
176
+ reply.send({ hello: 'world' })
177
+ }
178
+ })
179
+ ```
180
+
181
+ ### Shorthand declaration
182
+ <a id="shorthand-declaration"></a>
183
+
184
+ The above route declaration is more *Hapi*-like, but if you prefer an
185
+ *Express/Restify* approach, we support it as well:
186
+
187
+ `fastify.get(path, [options], handler)`
188
+
189
+ `fastify.head(path, [options], handler)`
190
+
191
+ `fastify.post(path, [options], handler)`
192
+
193
+ `fastify.put(path, [options], handler)`
194
+
195
+ `fastify.delete(path, [options], handler)`
196
+
197
+ `fastify.options(path, [options], handler)`
198
+
199
+ `fastify.patch(path, [options], handler)`
200
+
201
+ Example:
202
+ ```js
203
+ const opts = {
204
+ schema: {
205
+ response: {
206
+ 200: {
207
+ type: 'object',
208
+ properties: {
209
+ hello: { type: 'string' }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ fastify.get('/', opts, (request, reply) => {
216
+ reply.send({ hello: 'world' })
217
+ })
218
+ ```
219
+
220
+ `fastify.all(path, [options], handler)` will add the same handler to all the
221
+ supported methods.
222
+
223
+ The handler may also be supplied via the `options` object:
224
+ ```js
225
+ const opts = {
226
+ schema: {
227
+ response: {
228
+ 200: {
229
+ type: 'object',
230
+ properties: {
231
+ hello: { type: 'string' }
232
+ }
233
+ }
234
+ }
235
+ },
236
+ handler: function (request, reply) {
237
+ reply.send({ hello: 'world' })
238
+ }
239
+ }
240
+ fastify.get('/', opts)
241
+ ```
242
+
243
+ > ℹ️ Note:
244
+ > Specifying the handler in both `options` and as the third parameter to
245
+ > the shortcut method throws a duplicate `handler` error.
246
+
247
+ ### Url building
248
+ <a id="url-building"></a>
249
+
250
+ Fastify supports both static and dynamic URLs.
251
+
252
+ To register a **parametric** path, use a *colon* before the parameter name. For
253
+ **wildcard**, use a *star*. Static routes are always checked before parametric
254
+ and wildcard routes.
255
+
256
+ ```js
257
+ // parametric
258
+ fastify.get('/example/:userId', function (request, reply) {
259
+ // curl ${app-url}/example/12345
260
+ // userId === '12345'
261
+ const { userId } = request.params;
262
+ // your code here
263
+ })
264
+ fastify.get('/example/:userId/:secretToken', function (request, reply) {
265
+ // curl ${app-url}/example/12345/abc.zHi
266
+ // userId === '12345'
267
+ // secretToken === 'abc.zHi'
268
+ const { userId, secretToken } = request.params;
269
+ // your code here
270
+ })
271
+
272
+ // wildcard
273
+ fastify.get('/example/*', function (request, reply) {})
274
+ ```
275
+
276
+ Regular expression routes are supported, but slashes must be escaped.
277
+ Take note that RegExp is also very expensive in terms of performance!
278
+ ```js
279
+ // parametric with regexp
280
+ fastify.get('/example/:file(^\\d+).png', function (request, reply) {
281
+ // curl ${app-url}/example/12345.png
282
+ // file === '12345'
283
+ const { file } = request.params;
284
+ // your code here
285
+ })
286
+ ```
287
+
288
+ It is possible to define more than one parameter within the same couple of slash
289
+ ("/"). Such as:
290
+ ```js
291
+ fastify.get('/example/near/:lat-:lng/radius/:r', function (request, reply) {
292
+ // curl ${app-url}/example/near/15°N-30°E/radius/20
293
+ // lat === "15°N"
294
+ // lng === "30°E"
295
+ // r ==="20"
296
+ const { lat, lng, r } = request.params;
297
+ // your code here
298
+ })
299
+ ```
300
+ *Remember in this case to use the dash ("-") as parameters separator.*
301
+
302
+ Finally, it is possible to have multiple parameters with RegExp:
303
+ ```js
304
+ fastify.get('/example/at/:hour(^\\d{2})h:minute(^\\d{2})m', function (request, reply) {
305
+ // curl ${app-url}/example/at/08h24m
306
+ // hour === "08"
307
+ // minute === "24"
308
+ const { hour, minute } = request.params;
309
+ // your code here
310
+ })
311
+ ```
312
+ In this case as parameter separator it is possible to use whatever character is
313
+ not matched by the regular expression.
314
+
315
+ The last parameter can be made optional by adding a question mark ("?") to the
316
+ end of the parameter name.
317
+ ```js
318
+ fastify.get('/example/posts/:id?', function (request, reply) {
319
+ const { id } = request.params;
320
+ // your code here
321
+ })
322
+ ```
323
+ In this case, `/example/posts` and `/example/posts/1` are both valid. The
324
+ optional param will be `undefined` if not specified.
325
+
326
+ Having a route with multiple parameters may negatively affect performance.
327
+ Prefer a single parameter approach, especially on routes that are on the hot
328
+ path of your application. For more details, see
329
+ [find-my-way](https://github.com/delvedor/find-my-way).
330
+
331
+ To include a colon in a path without declaring a parameter, use a double colon.
332
+ For example:
333
+ ```js
334
+ fastify.post('/name::verb') // will be interpreted as /name:verb
335
+ ```
336
+
337
+ ### Async Await
338
+ <a id="async-await"></a>
339
+
340
+ Are you an `async/await` user? We have you covered!
341
+ ```js
342
+ fastify.get('/', options, async function (request, reply) {
343
+ const data = await getData()
344
+ const processed = await processData(data)
345
+ return processed
346
+ })
347
+ ```
348
+
349
+ As shown, `reply.send` is not called to send data back to the user. Simply
350
+ return the body and you are done!
351
+
352
+ If needed, you can also send data back with `reply.send`. In this case, do not
353
+ forget to `return reply` or `await reply` in your `async` handler to avoid race
354
+ conditions.
355
+
356
+ ```js
357
+ fastify.get('/', options, async function (request, reply) {
358
+ const data = await getData()
359
+ const processed = await processData(data)
360
+ return reply.send(processed)
361
+ })
362
+ ```
363
+
364
+ If the route is wrapping a callback-based API that will call `reply.send()`
365
+ outside of the promise chain, it is possible to `await reply`:
366
+
367
+ ```js
368
+ fastify.get('/', options, async function (request, reply) {
369
+ setImmediate(() => {
370
+ reply.send({ hello: 'world' })
371
+ })
372
+ await reply
373
+ })
374
+ ```
375
+
376
+ Returning reply also works:
377
+
378
+ ```js
379
+ fastify.get('/', options, async function (request, reply) {
380
+ setImmediate(() => {
381
+ reply.send({ hello: 'world' })
382
+ })
383
+ return reply
384
+ })
385
+ ```
386
+
387
+ > ⚠ Warning:
388
+ > * When using both `return value` and `reply.send(value)`, the first one takes
389
+ > precedence, the second is discarded, and a *warn* log is emitted.
390
+ > * Calling `reply.send()` outside of the promise is possible but requires special
391
+ > attention. See [promise-resolution](#promise-resolution).
392
+ > * `undefined` cannot be returned. See [promise-resolution](#promise-resolution).
393
+
394
+ ### Promise resolution
395
+ <a id="promise-resolution"></a>
396
+
397
+ If the handler is an `async` function or returns a promise, be aware of the
398
+ special behavior to support callback and promise control-flow. When the
399
+ handler's promise resolves, the reply is automatically sent with its value
400
+ unless you explicitly await or return `reply` in the handler.
401
+
402
+ 1. If using `async/await` or promises but responding with `reply.send`:
403
+ - **Do** `return reply` / `await reply`.
404
+ - **Do not** forget to call `reply.send`.
405
+ 2. If using `async/await` or promises:
406
+ - **Do not** use `reply.send`.
407
+ - **Do** return the value to send.
408
+
409
+ This approach supports both `callback-style` and `async-await` with minimal
410
+ trade-off. However, it is recommended to use only one style for consistent
411
+ error handling within your application.
412
+
413
+ > ℹ️ Note:
414
+ > Every async function returns a promise by itself.
415
+
416
+ ### Route Prefixing
417
+ <a id="route-prefixing"></a>
418
+
419
+ Sometimes maintaining multiple versions of the same API is necessary. A common
420
+ approach is to prefix routes with the API version number, e.g., `/v1/user`.
421
+ Fastify offers a fast and smart way to create different versions of the same API
422
+ without changing all the route names by hand, called *route prefixing*. Here is
423
+ how it works:
424
+
425
+ ```js
426
+ // server.js
427
+ const fastify = require('fastify')()
428
+
429
+ fastify.register(require('./routes/v1/users'), { prefix: '/v1' })
430
+ fastify.register(require('./routes/v2/users'), { prefix: '/v2' })
431
+
432
+ fastify.listen({ port: 3000 })
433
+ ```
434
+
435
+ ```js
436
+ // routes/v1/users.js
437
+ module.exports = function (fastify, opts, done) {
438
+ fastify.get('/user', handler_v1)
439
+ done()
440
+ }
441
+ ```
442
+
443
+ ```js
444
+ // routes/v2/users.js
445
+ module.exports = function (fastify, opts, done) {
446
+ fastify.get('/user', handler_v2)
447
+ done()
448
+ }
449
+ ```
450
+ Fastify will not complain about using the same name for two different routes
451
+ because it handles the prefix automatically at compilation time. This ensures
452
+ performance is not affected.
453
+
454
+ Now clients will have access to the following routes:
455
+ - `/v1/user`
456
+ - `/v2/user`
457
+
458
+ This can be done multiple times and works for nested `register`. Route
459
+ parameters are also supported.
460
+
461
+ To use a prefix for all routes, place them inside a plugin:
462
+
463
+ ```js
464
+ const fastify = require('fastify')()
465
+
466
+ const route = {
467
+ method: 'POST',
468
+ url: '/login',
469
+ handler: () => {},
470
+ schema: {},
471
+ }
472
+
473
+ fastify.register(function (app, _, done) {
474
+ app.get('/users', () => {})
475
+ app.route(route)
476
+
477
+ done()
478
+ }, { prefix: '/v1' }) // global route prefix
479
+
480
+ await fastify.listen({ port: 3000 })
481
+ ```
482
+
483
+ ### Route Prefixing and fastify-plugin
484
+ <a id="fastify-plugin"></a>
485
+
486
+ If using [`fastify-plugin`](https://github.com/fastify/fastify-plugin) to wrap
487
+ routes, this option will not work. To make it work, wrap a plugin in a plugin:
488
+ ```js
489
+ const fp = require('fastify-plugin')
490
+ const routes = require('./lib/routes')
491
+
492
+ module.exports = fp(async function (app, opts) {
493
+ app.register(routes, {
494
+ prefix: '/v1',
495
+ })
496
+ }, {
497
+ name: 'my-routes'
498
+ })
499
+ ```
500
+
501
+ #### Handling of / route inside prefixed plugins
502
+
503
+ The `/` route behaves differently based on whether the prefix ends with `/`.
504
+ For example, with a prefix `/something/`, adding a `/` route matches only
505
+ `/something/`. With a prefix `/something`, adding a `/` route matches both
506
+ `/something` and `/something/`.
507
+
508
+ See the `prefixTrailingSlash` route option above to change this behavior.
509
+
510
+ ### Custom Log Level
511
+ <a id="custom-log-level"></a>
512
+
513
+ Different log levels can be set for routes in Fastify by passing the `logLevel`
514
+ option to the plugin or route with the desired
515
+ [value](https://github.com/pinojs/pino/blob/main/docs/api.md#level-string).
516
+
517
+ Be aware that setting `logLevel` at the plugin level also affects
518
+ [`setNotFoundHandler`](./Server.md#setnotfoundhandler) and
519
+ [`setErrorHandler`](./Server.md#seterrorhandler).
520
+
521
+ ```js
522
+ // server.js
523
+ const fastify = require('fastify')({ logger: true })
524
+
525
+ fastify.register(require('./routes/user'), { logLevel: 'warn' })
526
+ fastify.register(require('./routes/events'), { logLevel: 'debug' })
527
+
528
+ fastify.listen({ port: 3000 })
529
+ ```
530
+
531
+ Or pass it directly to a route:
532
+ ```js
533
+ fastify.get('/', { logLevel: 'warn' }, (request, reply) => {
534
+ reply.send({ hello: 'world' })
535
+ })
536
+ ```
537
+ *Remember that the custom log level applies only to routes, not to the global
538
+ Fastify Logger, accessible with `fastify.log`.*
539
+
540
+ ### Custom Log Serializer
541
+ <a id="custom-log-serializer"></a>
542
+
543
+ In some contexts, logging a large object may waste resources. Define custom
544
+ [`serializers`](https://github.com/pinojs/pino/blob/main/docs/api.md#serializers-object)
545
+ and attach them in the appropriate context.
546
+
547
+ ```js
548
+ const fastify = require('fastify')({ logger: true })
549
+
550
+ fastify.register(require('./routes/user'), {
551
+ logSerializers: {
552
+ user: (value) => `My serializer one - ${value.name}`
553
+ }
554
+ })
555
+ fastify.register(require('./routes/events'), {
556
+ logSerializers: {
557
+ user: (value) => `My serializer two - ${value.name} ${value.surname}`
558
+ }
559
+ })
560
+
561
+ fastify.listen({ port: 3000 })
562
+ ```
563
+
564
+ Serializers can be inherited by context:
565
+
566
+ ```js
567
+ const fastify = Fastify({
568
+ logger: {
569
+ level: 'info',
570
+ serializers: {
571
+ user (req) {
572
+ return {
573
+ method: req.method,
574
+ url: req.url,
575
+ headers: req.headers,
576
+ host: req.host,
577
+ remoteAddress: req.ip,
578
+ remotePort: req.socket.remotePort
579
+ }
580
+ }
581
+ }
582
+ }
583
+ })
584
+
585
+ fastify.register(context1, {
586
+ logSerializers: {
587
+ user: value => `My serializer father - ${value}`
588
+ }
589
+ })
590
+
591
+ async function context1 (fastify, opts) {
592
+ fastify.get('/', (req, reply) => {
593
+ req.log.info({ user: 'call father serializer', key: 'another key' })
594
+ // shows: { user: 'My serializer father - call father serializer', key: 'another key' }
595
+ reply.send({})
596
+ })
597
+ }
598
+
599
+ fastify.listen({ port: 3000 })
600
+ ```
601
+
602
+ ### Config
603
+ <a id="routes-config"></a>
604
+
605
+ Registering a new handler, you can pass a configuration object to it and
606
+ retrieve it in the handler.
607
+
608
+ ```js
609
+ // server.js
610
+ const fastify = require('fastify')()
611
+
612
+ function handler (req, reply) {
613
+ reply.send(reply.routeOptions.config.output)
614
+ }
615
+
616
+ fastify.get('/en', { config: { output: 'hello world!' } }, handler)
617
+ fastify.get('/it', { config: { output: 'ciao mondo!' } }, handler)
618
+
619
+ fastify.listen({ port: 3000 })
620
+ ```
621
+
622
+ ### Constraints
623
+ <a id="constraints"></a>
624
+
625
+ Fastify supports constraining routes to match certain requests based on
626
+ properties like the `Host` header or any other value via
627
+ [`find-my-way`](https://github.com/delvedor/find-my-way) constraints.
628
+ Constraints are specified in the `constraints` property of the route options.
629
+ Fastify has two built-in constraints: `version` and `host`. Custom constraint
630
+ strategies can be added to inspect other parts of a request to decide if a route
631
+ should be executed.
632
+
633
+ #### Version Constraints
634
+
635
+ You can provide a `version` key in the `constraints` option to a route.
636
+ Versioned routes allows multiple handlers to be declared for the same HTTP
637
+ route path, matched according to the request's `Accept-Version` header.
638
+ The `Accept-Version` header value should follow the
639
+ [semver](https://semver.org/) specification, and routes should be declared
640
+ with exact semver versions for matching.
641
+
642
+ Fastify will require a request `Accept-Version` header to be set if the route
643
+ has a version set, and will prefer a versioned route to a non-versioned route
644
+ for the same path. Advanced version ranges and pre-releases currently are not
645
+ supported.
646
+
647
+ > ℹ️ Note:
648
+ > Using this feature can degrade the router's performance.
649
+
650
+ ```js
651
+ fastify.route({
652
+ method: 'GET',
653
+ url: '/',
654
+ constraints: { version: '1.2.0' },
655
+ handler: function (request, reply) {
656
+ reply.send({ hello: 'world' })
657
+ }
658
+ })
659
+
660
+ fastify.inject({
661
+ method: 'GET',
662
+ url: '/',
663
+ headers: {
664
+ 'Accept-Version': '1.x' // it could also be '1.2.0' or '1.2.x'
665
+ }
666
+ }, (err, res) => {
667
+ // { hello: 'world' }
668
+ })
669
+ ```
670
+
671
+ > ⚠ Warning:
672
+ > Set a
673
+ > [`Vary`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary)
674
+ > header in responses with the value used for versioning
675
+ > (e.g., `'Accept-Version'`) to prevent cache poisoning attacks.
676
+ > This can also be configured in a Proxy/CDN.
677
+ >
678
+ > ```js
679
+ > const append = require('vary').append
680
+ > fastify.addHook('onSend', (req, reply, payload, done) => {
681
+ > if (req.headers['accept-version']) { // or the custom header being used
682
+ > let value = reply.getHeader('Vary') || ''
683
+ > const header = Array.isArray(value) ? value.join(', ') : String(value)
684
+ > if ((value = append(header, 'Accept-Version'))) { // or the custom header being used
685
+ > reply.header('Vary', value)
686
+ > }
687
+ > }
688
+ > done()
689
+ > })
690
+ > ```
691
+
692
+ If multiple versions with the same major or minor are declared, Fastify will
693
+ always choose the highest compatible with the `Accept-Version` header value.
694
+
695
+ If the request lacks an `Accept-Version` header, a 404 error will be returned.
696
+
697
+ Custom version matching logic can be defined through the
698
+ [`constraints`](./Server.md#constraints) configuration when creating a Fastify
699
+ server instance.
700
+
701
+ #### Host Constraints
702
+
703
+ Provide a `host` key in the `constraints` route option to limit the route to
704
+ certain values of the request `Host` header. `host` constraint values can be
705
+ specified as strings for exact matches or RegExps for arbitrary host matching.
706
+
707
+ ```js
708
+ fastify.route({
709
+ method: 'GET',
710
+ url: '/',
711
+ constraints: { host: 'auth.fastify.example' },
712
+ handler: function (request, reply) {
713
+ reply.send('hello world from auth.fastify.example')
714
+ }
715
+ })
716
+
717
+ fastify.inject({
718
+ method: 'GET',
719
+ url: '/',
720
+ headers: {
721
+ 'Host': 'fastify.example'
722
+ }
723
+ }, (err, res) => {
724
+ // 404 because the host doesn't match the constraint
725
+ })
726
+
727
+ fastify.inject({
728
+ method: 'GET',
729
+ url: '/',
730
+ headers: {
731
+ 'Host': 'auth.fastify.dev'
732
+ }
733
+ }, (err, res) => {
734
+ // => 'hello world from auth.fastify.dev'
735
+ })
736
+ ```
737
+
738
+ RegExp `host` constraints can also be specified allowing constraining to hosts
739
+ matching wildcard subdomains (or any other pattern):
740
+
741
+ ```js
742
+ fastify.route({
743
+ method: 'GET',
744
+ url: '/',
745
+ constraints: { host: /.*\.fastify\.example/ }, // will match any subdomain of fastify.dev
746
+ handler: function (request, reply) {
747
+ reply.send('hello world from ' + request.headers.host)
748
+ }
749
+ })
750
+ ```
751
+
752
+ #### Asynchronous Custom Constraints
753
+
754
+ Custom constraints can be provided, and the `constraint` criteria can be
755
+ fetched from another source such as a database. Use asynchronous custom
756
+ constraints as a last resort, as they impact router performance.
757
+
758
+ ```js
759
+ function databaseOperation(field, done) {
760
+ done(null, field)
761
+ }
762
+
763
+ const secret = {
764
+ // strategy name for referencing in the route handler `constraints` options
765
+ name: 'secret',
766
+ // storage factory for storing routes in the find-my-way route tree
767
+ storage: function () {
768
+ let handlers = {}
769
+ return {
770
+ get: (type) => { return handlers[type] || null },
771
+ set: (type, store) => { handlers[type] = store }
772
+ }
773
+ },
774
+ // function to get the value of the constraint from each incoming request
775
+ deriveConstraint: (req, ctx, done) => {
776
+ databaseOperation(req.headers['secret'], done)
777
+ },
778
+ // optional flag marking if handlers without constraints can match requests that have a value for this constraint
779
+ mustMatchWhenDerived: true
780
+ }
781
+ ```
782
+
783
+ > ⚠ Warning:
784
+ > When using asynchronous constraints, avoid returning errors inside the
785
+ > callback. If errors are unavoidable, provide a custom `frameworkErrors`
786
+ > handler to manage them. Otherwise, route selection may break or expose
787
+ > sensitive information.
788
+ >
789
+ > ```js
790
+ > const Fastify = require('fastify')
791
+ >
792
+ > const fastify = Fastify({
793
+ > frameworkErrors: function (err, req, res) {
794
+ > if (err instanceof Fastify.errorCodes.FST_ERR_ASYNC_CONSTRAINT) {
795
+ > res.code(400)
796
+ > return res.send("Invalid header provided")
797
+ > } else {
798
+ > res.send(err)
799
+ > }
800
+ > }
801
+ > })
802
+ > ```