fastify 5.3.3 → 5.4.0
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.
- package/README.md +2 -0
- package/build/build-validation.js +2 -1
- package/docs/Guides/Delay-Accepting-Requests.md +3 -3
- package/docs/Guides/Ecosystem.md +9 -5
- package/docs/Reference/ContentTypeParser.md +1 -1
- package/docs/Reference/Errors.md +2 -2
- package/docs/Reference/Hooks.md +14 -14
- package/docs/Reference/Logging.md +3 -3
- package/docs/Reference/Middleware.md +1 -1
- package/docs/Reference/Reply.md +8 -8
- package/docs/Reference/Request.md +1 -1
- package/docs/Reference/Routes.md +3 -3
- package/docs/Reference/Server.md +35 -21
- package/docs/Reference/Validation-and-Serialization.md +1 -1
- package/fastify.d.ts +2 -1
- package/fastify.js +14 -2
- package/lib/configValidator.js +1 -1
- package/lib/errors.js +6 -0
- package/lib/pluginOverride.js +3 -1
- package/lib/reply.js +7 -11
- package/lib/request.js +3 -10
- package/lib/symbols.js +1 -0
- package/lib/warnings.js +8 -0
- package/package.json +8 -4
- package/test/404s.test.js +226 -325
- package/test/allow-unsafe-regex.test.js +19 -48
- package/test/als.test.js +28 -40
- package/test/async-await.test.js +11 -2
- package/test/body-limit.test.js +41 -65
- package/test/build-certificate.js +1 -1
- package/test/custom-parser-async.test.js +17 -22
- package/test/decorator-namespace.test._js_ +3 -4
- package/test/diagnostics-channel/async-delay-request.test.js +7 -16
- package/test/diagnostics-channel/sync-delay-request.test.js +7 -16
- package/test/helper.js +1 -1
- package/test/hooks-async.test.js +248 -218
- package/test/hooks.test.js +910 -769
- package/test/http-methods/lock.test.js +31 -31
- package/test/http-methods/mkcol.test.js +5 -9
- package/test/http-methods/proppatch.test.js +23 -29
- package/test/http-methods/report.test.js +44 -69
- package/test/http-methods/search.test.js +67 -82
- package/test/http2/closing.test.js +38 -20
- package/test/http2/secure-with-fallback.test.js +28 -27
- package/test/https/https.test.js +56 -53
- package/test/internals/errors.test.js +1 -1
- package/test/internals/handle-request.test.js +49 -66
- package/test/issue-4959.test.js +12 -3
- package/test/listen.4.test.js +31 -43
- package/test/nullable-validation.test.js +33 -46
- package/test/output-validation.test.js +24 -26
- package/test/plugin.2.test.js +104 -86
- package/test/plugin.3.test.js +56 -35
- package/test/plugin.4.test.js +124 -119
- package/test/proto-poisoning.test.js +78 -97
- package/test/request-error.test.js +0 -46
- package/test/route-hooks.test.js +112 -92
- package/test/route-prefix.test.js +194 -133
- package/test/schema-serialization.test.js +177 -154
- package/test/schema-special-usage.test.js +165 -132
- package/test/schema-validation.test.js +242 -205
- package/test/set-error-handler.test.js +58 -1
- package/test/skip-reply-send.test.js +64 -69
- package/test/trust-proxy.test.js +32 -58
- package/test/types/fastify.test-d.ts +3 -0
- package/test/types/request.test-d.ts +1 -0
- package/test/url-rewriting.test.js +45 -62
- package/types/request.d.ts +1 -0
- package/.taprc +0 -7
- package/.vscode/settings.json +0 -22
package/README.md
CHANGED
|
@@ -306,6 +306,8 @@ listed in alphabetical order.
|
|
|
306
306
|
* [__Vincent Le Goff__](https://github.com/zekth)
|
|
307
307
|
* [__Luciano Mammino__](https://github.com/lmammino),
|
|
308
308
|
<https://twitter.com/loige>, <https://www.npmjs.com/~lmammino>
|
|
309
|
+
* [__Jean Michelet__](https://github.com/jean-michelet),
|
|
310
|
+
<https://www.npmjs.com/~jean-michelet>
|
|
309
311
|
* [__KaKa Ng__](https://github.com/climba03003),
|
|
310
312
|
<https://www.npmjs.com/~climba03003>
|
|
311
313
|
* [__Luis Orbaiceta__](https://github.com/luisorbaiceta),
|
|
@@ -42,7 +42,8 @@ const defaultInitOptions = {
|
|
|
42
42
|
requestIdLogLabel: 'reqId',
|
|
43
43
|
http2SessionTimeout: 72000, // 72 seconds
|
|
44
44
|
exposeHeadRoutes: true,
|
|
45
|
-
useSemicolonDelimiter: false
|
|
45
|
+
useSemicolonDelimiter: false,
|
|
46
|
+
allowErrorHandlerOverride: true // TODO: set to false in v6
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
const schema = {
|
|
@@ -529,9 +529,9 @@ since that was not one of the requests we asked our plugin to filter, it
|
|
|
529
529
|
succeeded. That could also be used as a means of informing an interested party
|
|
530
530
|
whether or not we were ready to serve requests (although `/ping` is more
|
|
531
531
|
commonly associated with *liveness* checks and that would be the responsibility
|
|
532
|
-
of a *readiness* check -- the curious reader can get more info on these
|
|
533
|
-
[
|
|
534
|
-
with the `ready` field. Below is the response to that request:
|
|
532
|
+
of a *readiness* check -- the curious reader can get more info on these
|
|
533
|
+
[terms](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes))
|
|
534
|
+
here with the `ready` field. Below is the response to that request:
|
|
535
535
|
|
|
536
536
|
```sh
|
|
537
537
|
HTTP/1.1 200 OK
|
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -152,6 +152,15 @@ section.
|
|
|
152
152
|
|
|
153
153
|
#### [Community](#community)
|
|
154
154
|
|
|
155
|
+
> ℹ️ Note:
|
|
156
|
+
> Fastify community plugins are part of the broader community efforts,
|
|
157
|
+
> and we are thankful for these contributions. However, they are not
|
|
158
|
+
> maintained by the Fastify team.
|
|
159
|
+
> Use them at your own discretion.
|
|
160
|
+
> If you find malicious code, please
|
|
161
|
+
> [open an issue](https://github.com/fastify/fastify/issues/new/choose) or
|
|
162
|
+
> submit a PR to remove the plugin from the list.
|
|
163
|
+
|
|
155
164
|
- [`@aaroncadillac/crudify-mongo`](https://github.com/aaroncadillac/crudify-mongo)
|
|
156
165
|
A simple way to add a crud in your fastify project.
|
|
157
166
|
- [`@applicazza/fastify-nextjs`](https://github.com/applicazza/fastify-nextjs)
|
|
@@ -193,11 +202,6 @@ section.
|
|
|
193
202
|
- [`@immobiliarelabs/fastify-metrics`](https://github.com/immobiliare/fastify-metrics)
|
|
194
203
|
Minimalistic and opinionated plugin that collects usage/process metrics and
|
|
195
204
|
dispatches to [statsd](https://github.com/statsd/statsd).
|
|
196
|
-
- [`@immobiliarelabs/fastify-sentry`](https://github.com/immobiliare/fastify-sentry)
|
|
197
|
-
Sentry errors handler that just works! Install, add your DSN and you're good
|
|
198
|
-
to go!
|
|
199
|
-
A plugin to implement [Lyra](https://github.com/nearform/lyra) search engine
|
|
200
|
-
on Fastify
|
|
201
205
|
- [`@inaiat/fastify-papr`](https://github.com/inaiat/fastify-papr)
|
|
202
206
|
A plugin to integrate [Papr](https://github.com/plexinc/papr),
|
|
203
207
|
the MongoDB ORM for TypeScript & MongoDB, with Fastify.
|
|
@@ -152,7 +152,7 @@ fastify.addContentTypeParser('text/xml', function (request, payload, done) {
|
|
|
152
152
|
})
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
>
|
|
155
|
+
> ℹ️ Note: `function(req, done)` and `async function(req)` are
|
|
156
156
|
> still supported but deprecated.
|
|
157
157
|
|
|
158
158
|
#### Body Parser
|
package/docs/Reference/Errors.md
CHANGED
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
- [FST_ERR_VALIDATION](#fst_err_validation)
|
|
98
98
|
- [FST_ERR_LISTEN_OPTIONS_INVALID](#fst_err_listen_options_invalid)
|
|
99
99
|
- [FST_ERR_ERROR_HANDLER_NOT_FN](#fst_err_error_handler_not_fn)
|
|
100
|
+
- [FST_ERR_ERROR_HANDLER_ALREADY_SET](#fst_err_error_handler_already_set)
|
|
100
101
|
|
|
101
102
|
### Error Handling In Node.js
|
|
102
103
|
<a id="error-handling"></a>
|
|
@@ -366,5 +367,4 @@ Below is a table with all the error codes used by Fastify.
|
|
|
366
367
|
| <a id="fst_err_plugin_invalid_async_handler">FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER</a> | The plugin being registered mixes async and callback styles. | - | [#5141](https://github.com/fastify/fastify/pull/5141) |
|
|
367
368
|
| <a id="fst_err_validation">FST_ERR_VALIDATION</a> | The Request failed the payload validation. | Check the request payload. | [#4824](https://github.com/fastify/fastify/pull/4824) |
|
|
368
369
|
| <a id="fst_err_listen_options_invalid">FST_ERR_LISTEN_OPTIONS_INVALID</a> | Invalid listen options. | Check the listen options. | [#4886](https://github.com/fastify/fastify/pull/4886) |
|
|
369
|
-
| <a id="fst_err_error_handler_not_fn">FST_ERR_ERROR_HANDLER_NOT_FN</a> | Error Handler must be a function | Provide a function to `setErrorHandler`. | [#5317](https://github.com/fastify/fastify/pull/5317) |
|
|
370
|
-
|
|
370
|
+
| <a id="fst_err_error_handler_not_fn">FST_ERR_ERROR_HANDLER_NOT_FN</a> | Error Handler must be a function | Provide a function to `setErrorHandler`. | [#5317](https://github.com/fastify/fastify/pull/5317) | <a id="fst_err_error_handler_already_set">FST_ERR_ERROR_HANDLER_ALREADY_SET</a> | Error Handler already set in this scope. Set `allowErrorHandlerOverride: true` to allow overriding. | By default, `setErrorHandler` can only be called once per encapsulation context. | [#6097](https://github.com/fastify/fastify/pull/6098) |
|
package/docs/Reference/Hooks.md
CHANGED
|
@@ -34,7 +34,7 @@ are Request/Reply hooks and application hooks:
|
|
|
34
34
|
- [Using Hooks to Inject Custom Properties](#using-hooks-to-inject-custom-properties)
|
|
35
35
|
- [Diagnostics Channel Hooks](#diagnostics-channel-hooks)
|
|
36
36
|
|
|
37
|
-
>
|
|
37
|
+
> ℹ️ Note: The `done` callback is not available when using `async`/`await` or
|
|
38
38
|
> returning a `Promise`. If you do invoke a `done` callback in this situation
|
|
39
39
|
> unexpected behavior may occur, e.g. duplicate invocation of handlers.
|
|
40
40
|
|
|
@@ -68,7 +68,7 @@ fastify.addHook('onRequest', async (request, reply) => {
|
|
|
68
68
|
})
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
>
|
|
71
|
+
> ℹ️ Note: In the [onRequest](#onrequest) hook, `request.body` will always be
|
|
72
72
|
> `undefined`, because the body parsing happens before the
|
|
73
73
|
> [preValidation](#prevalidation) hook.
|
|
74
74
|
|
|
@@ -98,16 +98,16 @@ fastify.addHook('preParsing', async (request, reply, payload) => {
|
|
|
98
98
|
})
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
>
|
|
101
|
+
> ℹ️ Note: In the [preParsing](#preparsing) hook, `request.body` will always be
|
|
102
102
|
> `undefined`, because the body parsing happens before the
|
|
103
103
|
> [preValidation](#prevalidation) hook.
|
|
104
104
|
|
|
105
|
-
>
|
|
105
|
+
> ℹ️ Note: You should also add a `receivedEncodedLength` property to the
|
|
106
106
|
> returned stream. This property is used to correctly match the request payload
|
|
107
107
|
> with the `Content-Length` header value. Ideally, this property should be updated
|
|
108
108
|
> on each received chunk.
|
|
109
109
|
|
|
110
|
-
>
|
|
110
|
+
> ℹ️ Note: The size of the returned stream is checked to not exceed the limit
|
|
111
111
|
> set in [`bodyLimit`](./Server.md#bodylimit) option.
|
|
112
112
|
|
|
113
113
|
### preValidation
|
|
@@ -166,7 +166,7 @@ fastify.addHook('preSerialization', async (request, reply, payload) => {
|
|
|
166
166
|
})
|
|
167
167
|
```
|
|
168
168
|
|
|
169
|
-
>
|
|
169
|
+
> ℹ️ Note: The hook is NOT called if the payload is a `string`, a `Buffer`, a
|
|
170
170
|
> `stream`, or `null`.
|
|
171
171
|
|
|
172
172
|
### onError
|
|
@@ -196,7 +196,7 @@ user
|
|
|
196
196
|
*(Note that the default error handler always sends the error back to the
|
|
197
197
|
user)*.
|
|
198
198
|
|
|
199
|
-
>
|
|
199
|
+
> ℹ️ Note: Unlike the other hooks, passing an error to the `done` function is not
|
|
200
200
|
> supported.
|
|
201
201
|
|
|
202
202
|
### onSend
|
|
@@ -233,7 +233,7 @@ fastify.addHook('onSend', (request, reply, payload, done) => {
|
|
|
233
233
|
> to `0`, whereas the `Content-Length` header will not be set if the payload is
|
|
234
234
|
> `null`.
|
|
235
235
|
|
|
236
|
-
>
|
|
236
|
+
> ℹ️ Note: If you change the payload, you may only change it to a `string`, a
|
|
237
237
|
> `Buffer`, a `stream`, a `ReadableStream`, a `Response`, or `null`.
|
|
238
238
|
|
|
239
239
|
|
|
@@ -256,7 +256,7 @@ The `onResponse` hook is executed when a response has been sent, so you will not
|
|
|
256
256
|
be able to send more data to the client. It can however be useful for sending
|
|
257
257
|
data to external services, for example, to gather statistics.
|
|
258
258
|
|
|
259
|
-
>
|
|
259
|
+
> ℹ️ Note: Setting `disableRequestLogging` to `true` will disable any error log
|
|
260
260
|
> inside the `onResponse` hook. In this case use `try - catch` to log errors.
|
|
261
261
|
|
|
262
262
|
### onTimeout
|
|
@@ -298,7 +298,7 @@ The `onRequestAbort` hook is executed when a client closes the connection before
|
|
|
298
298
|
the entire request has been processed. Therefore, you will not be able to send
|
|
299
299
|
data to the client.
|
|
300
300
|
|
|
301
|
-
>
|
|
301
|
+
> ℹ️ Note: Client abort detection is not completely reliable.
|
|
302
302
|
> See: [`Detecting-When-Clients-Abort.md`](../Guides/Detecting-When-Clients-Abort.md)
|
|
303
303
|
|
|
304
304
|
### Manage Errors from a hook
|
|
@@ -452,7 +452,7 @@ fastify.addHook('onListen', async function () {
|
|
|
452
452
|
})
|
|
453
453
|
```
|
|
454
454
|
|
|
455
|
-
>
|
|
455
|
+
> ℹ️ Note: This hook will not run when the server is started using
|
|
456
456
|
> fastify.inject()` or `fastify.ready()`.
|
|
457
457
|
|
|
458
458
|
### onClose
|
|
@@ -576,7 +576,7 @@ This hook can be useful if you are developing a plugin that needs to know when a
|
|
|
576
576
|
plugin context is formed, and you want to operate in that specific context, thus
|
|
577
577
|
this hook is encapsulated.
|
|
578
578
|
|
|
579
|
-
>
|
|
579
|
+
> ℹ️ Note: This hook will not be called if a plugin is wrapped inside
|
|
580
580
|
> [`fastify-plugin`](https://github.com/fastify/fastify-plugin).
|
|
581
581
|
```js
|
|
582
582
|
fastify.decorate('data', [])
|
|
@@ -774,7 +774,7 @@ fastify.route({
|
|
|
774
774
|
})
|
|
775
775
|
```
|
|
776
776
|
|
|
777
|
-
>
|
|
777
|
+
> ℹ️ Note: Both options also accept an array of functions.
|
|
778
778
|
|
|
779
779
|
## Using Hooks to Inject Custom Properties
|
|
780
780
|
<a id="using-hooks-to-inject-custom-properties"></a>
|
|
@@ -861,7 +861,7 @@ channel.subscribe(function ({ fastify }) {
|
|
|
861
861
|
})
|
|
862
862
|
```
|
|
863
863
|
|
|
864
|
-
>
|
|
864
|
+
> ℹ️ Note: The TracingChannel class API is currently experimental and may undergo
|
|
865
865
|
> breaking changes even in semver-patch releases of Node.js.
|
|
866
866
|
|
|
867
867
|
Five other events are published on a per-request basis following the
|
|
@@ -157,7 +157,7 @@ const fastify = require('fastify')({
|
|
|
157
157
|
});
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
-
>
|
|
160
|
+
> ℹ️ Note: In some cases, the [`Reply`](./Reply.md) object passed to the `res`
|
|
161
161
|
> serializer cannot be fully constructed. When writing a custom `res`
|
|
162
162
|
> serializer, check for the existence of any properties on `reply` aside from
|
|
163
163
|
> `statusCode`, which is always present. For example, verify the existence of
|
|
@@ -184,7 +184,7 @@ const fastify = require('fastify')({
|
|
|
184
184
|
});
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
-
>
|
|
187
|
+
> ℹ️ Note: The body cannot be serialized inside a `req` method because the
|
|
188
188
|
request is serialized when the child logger is created. At that time, the body
|
|
189
189
|
is not yet parsed.
|
|
190
190
|
|
|
@@ -199,7 +199,7 @@ app.addHook('preHandler', function (req, reply, done) {
|
|
|
199
199
|
})
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
>
|
|
202
|
+
> ℹ️ Note: Ensure serializers never throw errors, as this can cause the Node
|
|
203
203
|
> process to exit. See the
|
|
204
204
|
> [Pino documentation](https://getpino.io/#/docs/api?id=opt-serializers) for more
|
|
205
205
|
> information.
|
|
@@ -50,7 +50,7 @@ that already has the Fastify [Request](./Request.md#request) and
|
|
|
50
50
|
To run middleware under certain paths, pass the path as the first parameter to
|
|
51
51
|
`use`.
|
|
52
52
|
|
|
53
|
-
>
|
|
53
|
+
> ℹ️ Note: This does not support routes with parameters
|
|
54
54
|
> (e.g. `/user/:id/comments`) and wildcards are not supported in multiple paths.
|
|
55
55
|
|
|
56
56
|
```js
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -151,7 +151,7 @@ fastify.get('/', async function (req, rep) {
|
|
|
151
151
|
Sets a response header. If the value is omitted or undefined, it is coerced to
|
|
152
152
|
`''`.
|
|
153
153
|
|
|
154
|
-
>
|
|
154
|
+
> ℹ️ Note: The header's value must be properly encoded using
|
|
155
155
|
> [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
|
|
156
156
|
> or similar modules such as
|
|
157
157
|
> [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid characters
|
|
@@ -260,10 +260,10 @@ requires heavy resources to be sent after the `data`, for example,
|
|
|
260
260
|
`Server-Timing` and `Etag`. It can ensure the client receives the response data
|
|
261
261
|
as soon as possible.
|
|
262
262
|
|
|
263
|
-
>
|
|
263
|
+
> ℹ️ Note: The header `Transfer-Encoding: chunked` will be added once you use
|
|
264
264
|
> the trailer. It is a hard requirement for using trailer in Node.js.
|
|
265
265
|
|
|
266
|
-
>
|
|
266
|
+
> ℹ️ Note: Any error passed to `done` callback will be ignored. If you interested
|
|
267
267
|
> in the error, you can turn on `debug` level logging.*
|
|
268
268
|
|
|
269
269
|
```js
|
|
@@ -279,14 +279,14 @@ const { createHash } = require('node:crypto')
|
|
|
279
279
|
reply.trailer('content-md5', function(reply, payload, done) {
|
|
280
280
|
const hash = createHash('md5')
|
|
281
281
|
hash.update(payload)
|
|
282
|
-
done(null, hash.
|
|
282
|
+
done(null, hash.digest('hex'))
|
|
283
283
|
})
|
|
284
284
|
|
|
285
285
|
// when you prefer async-await
|
|
286
286
|
reply.trailer('content-md5', async function(reply, payload) {
|
|
287
287
|
const hash = createHash('md5')
|
|
288
288
|
hash.update(payload)
|
|
289
|
-
return hash.
|
|
289
|
+
return hash.digest('hex')
|
|
290
290
|
})
|
|
291
291
|
```
|
|
292
292
|
|
|
@@ -314,7 +314,7 @@ reply.getTrailer('server-timing') // undefined
|
|
|
314
314
|
Redirects a request to the specified URL, the status code is optional, default
|
|
315
315
|
to `302` (if status code is not already set by calling `code`).
|
|
316
316
|
|
|
317
|
-
>
|
|
317
|
+
> ℹ️ Note: The input URL must be properly encoded using
|
|
318
318
|
> [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
|
|
319
319
|
> or similar modules such as
|
|
320
320
|
> [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid URLs will
|
|
@@ -823,7 +823,7 @@ automatically create an error structured as the following:
|
|
|
823
823
|
You can add custom properties to the Error object, such as `headers`, that will
|
|
824
824
|
be used to enhance the HTTP response.
|
|
825
825
|
|
|
826
|
-
>
|
|
826
|
+
> ℹ️ Note: If you are passing an error to `send` and the statusCode is less than
|
|
827
827
|
> 400, Fastify will automatically set it at 500.
|
|
828
828
|
|
|
829
829
|
Tip: you can simplify errors by using the
|
|
@@ -871,7 +871,7 @@ fastify.get('/', {
|
|
|
871
871
|
If you want to customize error handling, check out
|
|
872
872
|
[`setErrorHandler`](./Server.md#seterrorhandler) API.
|
|
873
873
|
|
|
874
|
-
>
|
|
874
|
+
> ℹ️ Note: you are responsible for logging when customizing the error handler.
|
|
875
875
|
|
|
876
876
|
API:
|
|
877
877
|
|
|
@@ -84,7 +84,7 @@ This operation adds new values to the request headers, accessible via
|
|
|
84
84
|
For performance reasons, `Symbol('fastify.RequestAcceptVersion')` may be added
|
|
85
85
|
to headers on `not found` routes.
|
|
86
86
|
|
|
87
|
-
>
|
|
87
|
+
> ℹ️ Note: Schema validation may mutate the `request.headers` and
|
|
88
88
|
> `request.raw.headers` objects, causing the headers to become empty.
|
|
89
89
|
|
|
90
90
|
```js
|
package/docs/Reference/Routes.md
CHANGED
|
@@ -137,7 +137,7 @@ fastify.route(options)
|
|
|
137
137
|
|
|
138
138
|
* `reply` is defined in [Reply](./Reply.md).
|
|
139
139
|
|
|
140
|
-
>
|
|
140
|
+
> ℹ️ Note: The documentation for `onRequest`, `preParsing`, `preValidation`,
|
|
141
141
|
> `preHandler`, `preSerialization`, `onSend`, and `onResponse` is detailed in
|
|
142
142
|
> [Hooks](./Hooks.md). To send a response before the request is handled by the
|
|
143
143
|
> `handler`, see [Respond to a request from
|
|
@@ -233,7 +233,7 @@ const opts = {
|
|
|
233
233
|
fastify.get('/', opts)
|
|
234
234
|
```
|
|
235
235
|
|
|
236
|
-
>
|
|
236
|
+
> ℹ️ Note: Specifying the handler in both `options` and as the third parameter to
|
|
237
237
|
> the shortcut method throws a duplicate `handler` error.
|
|
238
238
|
|
|
239
239
|
### Url building
|
|
@@ -402,7 +402,7 @@ This approach supports both `callback-style` and `async-await` with minimal
|
|
|
402
402
|
trade-off. However, it is recommended to use only one style for consistent
|
|
403
403
|
error handling within your application.
|
|
404
404
|
|
|
405
|
-
>
|
|
405
|
+
> ℹ️ Note: Every async function returns a promise by itself.
|
|
406
406
|
|
|
407
407
|
### Route Prefixing
|
|
408
408
|
<a id="route-prefixing"></a>
|
package/docs/Reference/Server.md
CHANGED
|
@@ -45,6 +45,7 @@ describes the properties available in that options object.
|
|
|
45
45
|
- [`clientErrorHandler`](#clienterrorhandler)
|
|
46
46
|
- [`rewriteUrl`](#rewriteurl)
|
|
47
47
|
- [`useSemicolonDelimiter`](#usesemicolondelimiter)
|
|
48
|
+
- [`allowErrorHandlerOverride`](#allowerrorhandleroverride)
|
|
48
49
|
- [Instance](#instance)
|
|
49
50
|
- [Server Methods](#server-methods)
|
|
50
51
|
- [server](#server)
|
|
@@ -193,7 +194,7 @@ to understand the effect of this option. This option only applies when HTTP/1.1
|
|
|
193
194
|
is in use. Also, when `serverFactory` option is specified, this option is
|
|
194
195
|
ignored.
|
|
195
196
|
|
|
196
|
-
>
|
|
197
|
+
> ℹ️ Note:
|
|
197
198
|
> At the time of writing, only node >= v16.10.0 supports this option.
|
|
198
199
|
|
|
199
200
|
### `requestTimeout`
|
|
@@ -211,7 +212,7 @@ It must be set to a non-zero value (e.g. 120 seconds) to protect against potenti
|
|
|
211
212
|
Denial-of-Service attacks in case the server is deployed without a reverse proxy
|
|
212
213
|
in front.
|
|
213
214
|
|
|
214
|
-
>
|
|
215
|
+
> ℹ️ Note:
|
|
215
216
|
> At the time of writing, only node >= v14.11.0 supports this option
|
|
216
217
|
|
|
217
218
|
### `ignoreTrailingSlash`
|
|
@@ -529,7 +530,7 @@ Especially in distributed systems, you may want to override the default ID
|
|
|
529
530
|
generation behavior as shown below. For generating `UUID`s you may want to check
|
|
530
531
|
out [hyperid](https://github.com/mcollina/hyperid).
|
|
531
532
|
|
|
532
|
-
>
|
|
533
|
+
> ℹ️ Note:
|
|
533
534
|
> `genReqId` will be not called if the header set in
|
|
534
535
|
> <code>[requestIdHeader](#requestidheader)</code> is available (defaults to
|
|
535
536
|
> 'request-id').
|
|
@@ -581,7 +582,7 @@ fastify.get('/', (request, reply) => {
|
|
|
581
582
|
})
|
|
582
583
|
```
|
|
583
584
|
|
|
584
|
-
>
|
|
585
|
+
> ℹ️ Note:
|
|
585
586
|
> If a request contains multiple `x-forwarded-host` or `x-forwarded-proto`
|
|
586
587
|
> headers, it is only the last one that is used to derive `request.hostname`
|
|
587
588
|
> and `request.protocol`.
|
|
@@ -736,7 +737,7 @@ Fastify provides default error handlers for the most common use cases. It is
|
|
|
736
737
|
possible to override one or more of those handlers with custom code using this
|
|
737
738
|
option.
|
|
738
739
|
|
|
739
|
-
>
|
|
740
|
+
> ℹ️ Note:
|
|
740
741
|
> Only `FST_ERR_BAD_URL` and `FST_ERR_ASYNC_CONSTRAINT` are implemented at present.
|
|
741
742
|
|
|
742
743
|
```js
|
|
@@ -789,7 +790,7 @@ function defaultClientErrorHandler (err, socket) {
|
|
|
789
790
|
}
|
|
790
791
|
```
|
|
791
792
|
|
|
792
|
-
>
|
|
793
|
+
> ℹ️ Note:
|
|
793
794
|
> `clientErrorHandler` operates with raw sockets. The handler is expected to
|
|
794
795
|
> return a properly formed HTTP response that includes a status line, HTTP headers
|
|
795
796
|
> and a message body. Before attempting to write the socket, the handler should
|
|
@@ -866,6 +867,29 @@ fastify.get('/dev', async (request, reply) => {
|
|
|
866
867
|
})
|
|
867
868
|
```
|
|
868
869
|
|
|
870
|
+
### `allowErrorHandlerOverride`
|
|
871
|
+
<a id="allow-error-handler-override"></a>
|
|
872
|
+
|
|
873
|
+
* **Default:** `true`
|
|
874
|
+
|
|
875
|
+
> ⚠ **Warning:** This option will be set to `false` by default
|
|
876
|
+
> in the next major release.
|
|
877
|
+
|
|
878
|
+
When set to `false`, it prevents `setErrorHandler` from being called
|
|
879
|
+
multiple times within the same scope, ensuring that the previous error
|
|
880
|
+
handler is not unintentionally overridden.
|
|
881
|
+
|
|
882
|
+
#### Example of incorrect usage:
|
|
883
|
+
|
|
884
|
+
```js
|
|
885
|
+
app.setErrorHandler(function freeSomeResources () {
|
|
886
|
+
// Never executed, memory leaks
|
|
887
|
+
})
|
|
888
|
+
|
|
889
|
+
app.setErrorHandler(function anotherErrorHandler () {
|
|
890
|
+
// Overrides the previous handler
|
|
891
|
+
})
|
|
892
|
+
```
|
|
869
893
|
|
|
870
894
|
## Instance
|
|
871
895
|
|
|
@@ -1357,7 +1381,7 @@ Set the schema error formatter for all routes. See
|
|
|
1357
1381
|
Set the schema serializer compiler for all routes. See
|
|
1358
1382
|
[#schema-serializer](./Validation-and-Serialization.md#schema-serializer).
|
|
1359
1383
|
|
|
1360
|
-
>
|
|
1384
|
+
> ℹ️ Note:
|
|
1361
1385
|
> [`setReplySerializer`](#set-reply-serializer) has priority if set!
|
|
1362
1386
|
|
|
1363
1387
|
#### validatorCompiler
|
|
@@ -1490,7 +1514,7 @@ lifecycle](./Lifecycle.md#lifecycle). *async-await* is supported as well.
|
|
|
1490
1514
|
You can also register [`preValidation`](./Hooks.md#route-hooks) and
|
|
1491
1515
|
[`preHandler`](./Hooks.md#route-hooks) hooks for the 404 handler.
|
|
1492
1516
|
|
|
1493
|
-
>
|
|
1517
|
+
> ℹ️ Note:
|
|
1494
1518
|
> The `preValidation` hook registered using this method will run for a
|
|
1495
1519
|
> route that Fastify does not recognize and **not** when a route handler manually
|
|
1496
1520
|
> calls [`reply.callNotFound`](./Reply.md#call-not-found). In which case, only
|
|
@@ -1526,7 +1550,7 @@ plugins are registered. If you would like to augment the behavior of the default
|
|
|
1526
1550
|
arguments `fastify.setNotFoundHandler()` within the context of these registered
|
|
1527
1551
|
plugins.
|
|
1528
1552
|
|
|
1529
|
-
>
|
|
1553
|
+
> ℹ️ Note:
|
|
1530
1554
|
> Some config properties from the request object will be
|
|
1531
1555
|
> undefined inside the custom not found handler. E.g.:
|
|
1532
1556
|
> `request.routeOptions.url`, `routeOptions.method` and `routeOptions.config`.
|
|
@@ -1577,18 +1601,8 @@ if (statusCode >= 500) {
|
|
|
1577
1601
|
|
|
1578
1602
|
> ⚠ Warning:
|
|
1579
1603
|
> Avoid calling setErrorHandler multiple times in the same scope.
|
|
1580
|
-
>
|
|
1581
|
-
|
|
1582
|
-
> Incorrect usage:
|
|
1583
|
-
> ```js
|
|
1584
|
-
> app.setErrorHandler(function freeSomeResources () {
|
|
1585
|
-
> // Never executed, memory leaks
|
|
1586
|
-
> })
|
|
1587
|
-
>
|
|
1588
|
-
> app.setErrorHandler(function anotherErrorHandler () {
|
|
1589
|
-
> // Overrides the previous handler
|
|
1590
|
-
> })
|
|
1591
|
-
> ```
|
|
1604
|
+
> See [`allowErrorHandlerOverride`](#allowerrorhandleroverride).
|
|
1605
|
+
|
|
1592
1606
|
|
|
1593
1607
|
#### setChildLoggerFactory
|
|
1594
1608
|
<a id="set-child-logger-factory"></a>
|
|
@@ -432,7 +432,7 @@ fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
|
|
|
432
432
|
return ajv.compile(schema)
|
|
433
433
|
})
|
|
434
434
|
```
|
|
435
|
-
>
|
|
435
|
+
> ℹ️ Note: When using a custom validator instance, add schemas to the validator
|
|
436
436
|
> instead of Fastify. Fastify's `addSchema` method will not recognize the custom
|
|
437
437
|
> validator.
|
|
438
438
|
|
package/fastify.d.ts
CHANGED
|
@@ -157,7 +157,8 @@ declare namespace fastify {
|
|
|
157
157
|
* listener to error events emitted by client connections
|
|
158
158
|
*/
|
|
159
159
|
clientErrorHandler?: (error: ConnectionError, socket: Socket) => void,
|
|
160
|
-
childLoggerFactory?: FastifyChildLoggerFactory
|
|
160
|
+
childLoggerFactory?: FastifyChildLoggerFactory,
|
|
161
|
+
allowErrorHandlerOverride?: boolean
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/**
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '5.
|
|
3
|
+
const VERSION = '5.4.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('node:http')
|
|
@@ -31,7 +31,8 @@ const {
|
|
|
31
31
|
kErrorHandler,
|
|
32
32
|
kKeepAliveConnections,
|
|
33
33
|
kChildLoggerFactory,
|
|
34
|
-
kGenReqId
|
|
34
|
+
kGenReqId,
|
|
35
|
+
kErrorHandlerAlreadySet
|
|
35
36
|
} = require('./lib/symbols.js')
|
|
36
37
|
|
|
37
38
|
const { createServer } = require('./lib/server')
|
|
@@ -72,10 +73,12 @@ const {
|
|
|
72
73
|
FST_ERR_ROUTE_REWRITE_NOT_STR,
|
|
73
74
|
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN,
|
|
74
75
|
FST_ERR_ERROR_HANDLER_NOT_FN,
|
|
76
|
+
FST_ERR_ERROR_HANDLER_ALREADY_SET,
|
|
75
77
|
FST_ERR_ROUTE_METHOD_INVALID
|
|
76
78
|
} = errorCodes
|
|
77
79
|
|
|
78
80
|
const { buildErrorHandler } = require('./lib/error-handler.js')
|
|
81
|
+
const { FSTWRN004 } = require('./lib/warnings.js')
|
|
79
82
|
|
|
80
83
|
const initChannel = diagnostics.channel('fastify.initialization')
|
|
81
84
|
|
|
@@ -149,6 +152,7 @@ function fastify (options) {
|
|
|
149
152
|
options.disableRequestLogging = disableRequestLogging
|
|
150
153
|
options.ajv = ajvOptions
|
|
151
154
|
options.clientErrorHandler = options.clientErrorHandler || defaultClientErrorHandler
|
|
155
|
+
options.allowErrorHandlerOverride = options.allowErrorHandlerOverride ?? defaultInitOptions.allowErrorHandlerOverride
|
|
152
156
|
|
|
153
157
|
const initialConfig = getSecuredInitialConfig(options)
|
|
154
158
|
|
|
@@ -237,6 +241,7 @@ function fastify (options) {
|
|
|
237
241
|
[kSchemaController]: schemaController,
|
|
238
242
|
[kSchemaErrorFormatter]: null,
|
|
239
243
|
[kErrorHandler]: buildErrorHandler(),
|
|
244
|
+
[kErrorHandlerAlreadySet]: false,
|
|
240
245
|
[kChildLoggerFactory]: defaultChildLoggerFactory,
|
|
241
246
|
[kReplySerializerDefault]: null,
|
|
242
247
|
[kContentTypeParser]: new ContentTypeParser(
|
|
@@ -858,6 +863,13 @@ function fastify (options) {
|
|
|
858
863
|
throw new FST_ERR_ERROR_HANDLER_NOT_FN()
|
|
859
864
|
}
|
|
860
865
|
|
|
866
|
+
if (!options.allowErrorHandlerOverride && this[kErrorHandlerAlreadySet]) {
|
|
867
|
+
throw new FST_ERR_ERROR_HANDLER_ALREADY_SET()
|
|
868
|
+
} else if (this[kErrorHandlerAlreadySet]) {
|
|
869
|
+
FSTWRN004("To disable this behavior, set 'allowErrorHandlerOverride' to false or ignore this message. For more information, visit: https://fastify.dev/docs/latest/Reference/Server/#allowerrorhandleroverride")
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
this[kErrorHandlerAlreadySet] = true
|
|
861
873
|
this[kErrorHandler] = buildErrorHandler(this[kErrorHandler], func.bind(this))
|
|
862
874
|
return this
|
|
863
875
|
}
|
package/lib/configValidator.js
CHANGED
|
@@ -1100,5 +1100,5 @@ return errors === 0;
|
|
|
1100
1100
|
}
|
|
1101
1101
|
|
|
1102
1102
|
|
|
1103
|
-
module.exports.defaultInitOptions = {"connectionTimeout":0,"keepAliveTimeout":72000,"maxRequestsPerSocket":0,"requestTimeout":0,"bodyLimit":1048576,"caseSensitive":true,"allowUnsafeRegex":false,"disableRequestLogging":false,"ignoreTrailingSlash":false,"ignoreDuplicateSlashes":false,"maxParamLength":100,"onProtoPoisoning":"error","onConstructorPoisoning":"error","pluginTimeout":10000,"requestIdHeader":false,"requestIdLogLabel":"reqId","http2SessionTimeout":72000,"exposeHeadRoutes":true,"useSemicolonDelimiter":false}
|
|
1103
|
+
module.exports.defaultInitOptions = {"connectionTimeout":0,"keepAliveTimeout":72000,"maxRequestsPerSocket":0,"requestTimeout":0,"bodyLimit":1048576,"caseSensitive":true,"allowUnsafeRegex":false,"disableRequestLogging":false,"ignoreTrailingSlash":false,"ignoreDuplicateSlashes":false,"maxParamLength":100,"onProtoPoisoning":"error","onConstructorPoisoning":"error","pluginTimeout":10000,"requestIdHeader":false,"requestIdLogLabel":"reqId","http2SessionTimeout":72000,"exposeHeadRoutes":true,"useSemicolonDelimiter":false,"allowErrorHandlerOverride":true}
|
|
1104
1104
|
/* c8 ignore stop */
|
package/lib/errors.js
CHANGED
|
@@ -64,6 +64,12 @@ const codes = {
|
|
|
64
64
|
500,
|
|
65
65
|
TypeError
|
|
66
66
|
),
|
|
67
|
+
FST_ERR_ERROR_HANDLER_ALREADY_SET: createError(
|
|
68
|
+
'FST_ERR_ERROR_HANDLER_ALREADY_SET',
|
|
69
|
+
"Error Handler already set in this scope. Set 'allowErrorHandlerOverride: true' to allow overriding.",
|
|
70
|
+
500,
|
|
71
|
+
TypeError
|
|
72
|
+
),
|
|
67
73
|
|
|
68
74
|
/**
|
|
69
75
|
* ContentTypeParser
|
package/lib/pluginOverride.js
CHANGED
|
@@ -12,7 +12,8 @@ const {
|
|
|
12
12
|
kReply,
|
|
13
13
|
kRequest,
|
|
14
14
|
kFourOhFour,
|
|
15
|
-
kPluginNameChain
|
|
15
|
+
kPluginNameChain,
|
|
16
|
+
kErrorHandlerAlreadySet
|
|
16
17
|
} = require('./symbols.js')
|
|
17
18
|
|
|
18
19
|
const Reply = require('./reply')
|
|
@@ -57,6 +58,7 @@ module.exports = function override (old, fn, opts) {
|
|
|
57
58
|
// Track the plugin chain since the root instance.
|
|
58
59
|
// When an non-encapsulated plugin is added, the chain will be updated.
|
|
59
60
|
instance[kPluginNameChain] = [fnName]
|
|
61
|
+
instance[kErrorHandlerAlreadySet] = false
|
|
60
62
|
|
|
61
63
|
if (instance[kLogSerializers] || opts.logSerializers) {
|
|
62
64
|
instance[kLogSerializers] = Object.assign(Object.create(instance[kLogSerializers]), opts.logSerializers)
|
package/lib/reply.js
CHANGED
|
@@ -215,12 +215,8 @@ Reply.prototype.send = function (payload) {
|
|
|
215
215
|
|
|
216
216
|
Reply.prototype.getHeader = function (key) {
|
|
217
217
|
key = key.toLowerCase()
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
if (value === undefined && res.hasHeader(key)) {
|
|
221
|
-
value = res.getHeader(key)
|
|
222
|
-
}
|
|
223
|
-
return value
|
|
218
|
+
const value = this[kReplyHeaders][key]
|
|
219
|
+
return value !== undefined ? value : this.raw.getHeader(key)
|
|
224
220
|
}
|
|
225
221
|
|
|
226
222
|
Reply.prototype.getHeaders = function () {
|
|
@@ -315,12 +311,12 @@ Reply.prototype.removeTrailer = function (key) {
|
|
|
315
311
|
}
|
|
316
312
|
|
|
317
313
|
Reply.prototype.code = function (code) {
|
|
318
|
-
const
|
|
319
|
-
if (
|
|
314
|
+
const statusCode = +code
|
|
315
|
+
if (!(statusCode >= 100 && statusCode <= 599)) {
|
|
320
316
|
throw new FST_ERR_BAD_STATUS_CODE(code || String(code))
|
|
321
317
|
}
|
|
322
318
|
|
|
323
|
-
this.raw.statusCode =
|
|
319
|
+
this.raw.statusCode = statusCode
|
|
324
320
|
this[kReplyHasStatusCode] = true
|
|
325
321
|
return this
|
|
326
322
|
}
|
|
@@ -500,11 +496,11 @@ function preSerializationHook (reply, payload) {
|
|
|
500
496
|
preSerializationHookEnd
|
|
501
497
|
)
|
|
502
498
|
} else {
|
|
503
|
-
preSerializationHookEnd(null,
|
|
499
|
+
preSerializationHookEnd(null, undefined, reply, payload)
|
|
504
500
|
}
|
|
505
501
|
}
|
|
506
502
|
|
|
507
|
-
function preSerializationHookEnd (err,
|
|
503
|
+
function preSerializationHookEnd (err, _request, reply, payload) {
|
|
508
504
|
if (err != null) {
|
|
509
505
|
onErrorHook(reply, err)
|
|
510
506
|
return
|