fastify 5.0.0 → 5.2.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/.borp.yaml +3 -0
- package/.vscode/settings.json +22 -0
- package/README.md +12 -7
- package/docs/Guides/Database.md +15 -15
- package/docs/Guides/Detecting-When-Clients-Abort.md +28 -28
- package/docs/Guides/Ecosystem.md +14 -15
- package/docs/Guides/Index.md +1 -1
- package/docs/Guides/Migration-Guide-V4.md +11 -11
- package/docs/Guides/Migration-Guide-V5.md +133 -9
- package/docs/Guides/Plugins-Guide.md +1 -1
- package/docs/Guides/Prototype-Poisoning.md +3 -3
- package/docs/Guides/Recommendations.md +9 -9
- package/docs/Guides/Serverless.md +5 -5
- package/docs/Guides/Testing.md +58 -57
- package/docs/Guides/Write-Plugin.md +2 -2
- package/docs/Guides/Write-Type-Provider.md +3 -3
- package/docs/Reference/ContentTypeParser.md +4 -4
- package/docs/Reference/Decorators.md +2 -2
- package/docs/Reference/Errors.md +3 -3
- package/docs/Reference/Hooks.md +7 -7
- package/docs/Reference/LTS.md +8 -0
- package/docs/Reference/Logging.md +5 -4
- package/docs/Reference/Reply.md +55 -58
- package/docs/Reference/Request.md +49 -42
- package/docs/Reference/Routes.md +16 -13
- package/docs/Reference/Server.md +32 -28
- package/docs/Reference/TypeScript.md +9 -9
- package/docs/Reference/Validation-and-Serialization.md +5 -5
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +14 -5
- package/fastify.js +8 -6
- package/lib/contentTypeParser.js +9 -7
- package/lib/context.js +1 -2
- package/lib/error-handler.js +9 -9
- package/lib/errors.js +1 -1
- package/lib/fourOhFour.js +1 -1
- package/lib/hooks.js +4 -1
- package/lib/{logger.js → logger-factory.js} +70 -122
- package/lib/logger-pino.js +68 -0
- package/lib/pluginOverride.js +1 -1
- package/lib/pluginUtils.js +2 -2
- package/lib/reply.js +4 -5
- package/lib/request.js +16 -9
- package/lib/route.js +23 -22
- package/lib/validation.js +2 -2
- package/package.json +13 -15
- package/test/404s.test.js +675 -629
- package/test/500s.test.js +72 -63
- package/test/{allowUnsafeRegex.test.js → allow-unsafe-regex.test.js} +30 -26
- package/test/als.test.js +48 -45
- package/test/async-await.test.js +148 -134
- package/test/async-dispose.test.js +4 -5
- package/test/async_hooks.test.js +30 -28
- package/test/{bodyLimit.test.js → body-limit.test.js} +61 -58
- package/test/buffer.test.js +9 -10
- package/test/build/error-serializer.test.js +3 -4
- package/test/build/version.test.js +2 -3
- package/test/build-certificate.js +1 -1
- package/test/bundler/README.md +5 -5
- package/test/bundler/esbuild/bundler-test.js +10 -9
- package/test/bundler/webpack/bundler-test.js +10 -9
- package/test/case-insensitive.test.js +31 -28
- package/test/chainable.test.js +4 -5
- package/test/check.test.js +8 -10
- package/test/{childLoggerFactory.test.js → child-logger-factory.test.js} +56 -19
- package/test/client-timeout.test.js +5 -5
- package/test/close-pipelining.test.js +6 -8
- package/test/conditional-pino.test.js +47 -0
- package/test/{connectionTimeout.test.js → connection-timeout.test.js} +10 -11
- package/test/constrained-routes.test.js +243 -236
- package/test/content-length.test.js +53 -68
- package/test/content-parser.test.js +186 -158
- package/test/content-type.test.js +8 -9
- package/test/context-config.test.js +44 -54
- package/test/custom-http-server.test.js +16 -20
- package/test/custom-parser.5.test.js +32 -32
- package/test/diagnostics-channel/404.test.js +15 -15
- package/test/diagnostics-channel/async-delay-request.test.js +25 -25
- package/test/diagnostics-channel/async-request.test.js +24 -24
- package/test/diagnostics-channel/error-before-handler.test.js +4 -5
- package/test/diagnostics-channel/error-request.test.js +19 -19
- package/test/diagnostics-channel/error-status.test.js +8 -8
- package/test/diagnostics-channel/init.test.js +6 -7
- package/test/diagnostics-channel/sync-delay-request.test.js +16 -16
- package/test/diagnostics-channel/sync-request-reply.test.js +16 -16
- package/test/diagnostics-channel/sync-request.test.js +19 -19
- package/test/encapsulated-child-logger-factory.test.js +8 -8
- package/test/encapsulated-error-handler.test.js +20 -20
- package/test/esm/errorCodes.test.mjs +5 -5
- package/test/esm/esm.test.mjs +3 -3
- package/test/esm/named-exports.mjs +3 -3
- package/test/esm/other.mjs +2 -2
- package/test/fastify-instance.test.js +33 -34
- package/test/{findRoute.test.js → find-route.test.js} +11 -10
- package/test/fluent-schema.test.js +33 -36
- package/test/handler-context.test.js +11 -11
- package/test/has-route.test.js +12 -15
- package/test/header-overflow.test.js +13 -12
- package/test/hooks.on-ready.test.js +2 -2
- package/test/hooks.test.js +25 -25
- package/test/http-methods/copy.test.js +22 -24
- package/test/http-methods/custom-http-methods.test.js +24 -21
- package/test/http-methods/get.test.js +97 -84
- package/test/http-methods/head.test.js +63 -57
- package/test/http-methods/lock.test.js +21 -20
- package/test/http-methods/mkcalendar.test.js +31 -27
- package/test/http-methods/mkcol.test.js +10 -10
- package/test/http-methods/move.test.js +11 -11
- package/test/http-methods/propfind.test.js +32 -27
- package/test/http-methods/proppatch.test.js +21 -19
- package/test/http-methods/report.test.js +32 -27
- package/test/http-methods/search.test.js +52 -47
- package/test/http-methods/trace.test.js +3 -4
- package/test/http-methods/unlock.test.js +10 -10
- package/test/http2/closing.test.js +50 -58
- package/test/http2/constraint.test.js +47 -50
- package/test/http2/head.test.js +18 -19
- package/test/http2/missing-http2-module.test.js +4 -5
- package/test/http2/plain.test.js +31 -31
- package/test/http2/secure-with-fallback.test.js +61 -61
- package/test/http2/secure.test.js +28 -31
- package/test/http2/unknown-http-method.test.js +13 -14
- package/test/https/custom-https-server.test.js +6 -7
- package/test/https/https.test.js +78 -78
- package/test/imports.test.js +5 -6
- package/test/internals/all.test.js +8 -11
- package/test/internals/{contentTypeParser.test.js → content-type-parser.test.js} +5 -6
- package/test/internals/context.test.js +9 -11
- package/test/internals/decorator.test.js +20 -21
- package/test/internals/errors.test.js +427 -427
- package/test/internals/{handleRequest.test.js → handle-request.test.js} +53 -42
- package/test/internals/{hookRunner.test.js → hook-runner.test.js} +99 -100
- package/test/internals/hooks.test.js +31 -35
- package/test/internals/{initialConfig.test.js → initial-config.test.js} +92 -80
- package/test/internals/logger.test.js +28 -28
- package/test/internals/plugin.test.js +17 -18
- package/test/internals/reply-serialize.test.js +106 -106
- package/test/internals/reply.test.js +620 -585
- package/test/internals/{reqIdGenFactory.test.js → req-id-gen-factory.test.js} +31 -31
- package/test/internals/request-validate.test.js +218 -221
- package/test/internals/request.test.js +225 -107
- package/test/internals/server.test.js +15 -12
- package/test/internals/validation.test.js +35 -36
- package/test/{keepAliveTimeout.test.js → keep-alive-timeout.test.js} +9 -10
- package/test/listen.5.test.js +9 -9
- package/test/{maxRequestsPerSocket.test.js → max-requests-per-socket.test.js} +30 -30
- package/test/middleware.test.js +4 -5
- package/test/noop-set.test.js +5 -5
- package/test/post-empty-body.test.js +18 -11
- package/test/pretty-print.test.js +59 -49
- package/test/proto-poisoning.test.js +42 -37
- package/test/reply-code.test.js +34 -32
- package/test/{reply-earlyHints.test.js → reply-early-hints.test.js} +21 -19
- package/test/request-error.test.js +122 -0
- package/test/request-header-host.test.js +339 -0
- package/test/request-id.test.js +31 -25
- package/test/{requestTimeout.test.js → request-timeout.test.js} +11 -11
- package/test/route.1.test.js +79 -72
- package/test/route.2.test.js +17 -16
- package/test/route.3.test.js +32 -27
- package/test/route.4.test.js +21 -25
- package/test/route.5.test.js +45 -64
- package/test/route.6.test.js +70 -89
- package/test/route.7.test.js +61 -65
- package/test/route.8.test.js +80 -18
- package/test/router-options.test.js +80 -77
- package/test/same-shape.test.js +5 -5
- package/test/schema-examples.test.js +72 -38
- package/test/serialize-response.test.js +9 -10
- package/test/server.test.js +75 -78
- package/test/set-error-handler.test.js +2 -3
- package/test/stream-serializers.test.js +10 -7
- package/test/sync-routes.test.js +18 -18
- package/test/test-reporter.mjs +68 -0
- package/test/trust-proxy.test.js +51 -45
- package/test/type-provider.test.js +8 -6
- package/test/types/content-type-parser.test-d.ts +1 -1
- package/test/types/fastify.test-d.ts +16 -4
- package/test/types/hooks.test-d.ts +2 -1
- package/test/types/instance.test-d.ts +13 -13
- package/test/types/logger.test-d.ts +2 -2
- package/test/types/plugin.test-d.ts +17 -9
- package/test/types/register.test-d.ts +22 -6
- package/test/types/reply.test-d.ts +1 -1
- package/test/types/route.test-d.ts +34 -4
- package/test/types/serverFactory.test-d.ts +1 -1
- package/test/types/type-provider.test-d.ts +1 -1
- package/test/url-rewriting.test.js +35 -38
- package/test/{useSemicolonDelimiter.test.js → use-semicolon-delimiter.test.js} +30 -30
- package/test/validation-error-handling.test.js +259 -285
- package/test/versioned-routes.test.js +126 -113
- package/test/web-api.test.js +48 -37
- package/test/{wrapThenable.test.js → wrap-thenable.test.js} +10 -9
- package/types/hooks.d.ts +2 -1
- package/types/instance.d.ts +9 -2
- package/types/register.d.ts +12 -3
- package/types/reply.d.ts +1 -1
- package/types/request.d.ts +2 -6
- package/types/serverFactory.d.ts +3 -3
- package/types/utils.d.ts +13 -5
- package/test/types/import.js +0 -2
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<a id="pp"></a>
|
|
9
9
|
|
|
10
10
|
Based on the article by Eran Hammer,the issue is created by a web security bug.
|
|
11
|
-
It is also a perfect illustration of the efforts required to maintain
|
|
11
|
+
It is also a perfect illustration of the efforts required to maintain
|
|
12
12
|
open-source software and the limitations of existing communication channels.
|
|
13
13
|
|
|
14
14
|
But first, if we use a JavaScript framework to process incoming JSON data, take
|
|
@@ -16,7 +16,7 @@ a moment to read up on [Prototype Poisoning](https://medium.com/intrinsic/javasc
|
|
|
16
16
|
in general, and the specific
|
|
17
17
|
[technical details](https://github.com/hapijs/hapi/issues/3916) of this issue.
|
|
18
18
|
This could be a critical issue so, we might need to verify your own code first.
|
|
19
|
-
It focuses on specific framework however, any solution that uses `JSON.parse()`
|
|
19
|
+
It focuses on specific framework however, any solution that uses `JSON.parse()`
|
|
20
20
|
to process external data is potentially at risk.
|
|
21
21
|
|
|
22
22
|
### BOOM
|
|
@@ -42,7 +42,7 @@ defect a validation library can have.
|
|
|
42
42
|
|
|
43
43
|
To understand this, we need to understand how JavaScript works a bit.
|
|
44
44
|
Every object in JavaScript can have a prototype. It is a set of methods and
|
|
45
|
-
properties it "inherits" from another object. I have put inherits in quotes
|
|
45
|
+
properties it "inherits" from another object. I have put inherits in quotes
|
|
46
46
|
because JavaScript isn't really an object-oriented language. It is a prototype-
|
|
47
47
|
based object-oriented language.
|
|
48
48
|
|
|
@@ -307,22 +307,22 @@ readinessProbe:
|
|
|
307
307
|
## Capacity Planning For Production
|
|
308
308
|
<a id="capacity"></a>
|
|
309
309
|
|
|
310
|
-
In order to rightsize the production environment for your Fastify application,
|
|
311
|
-
it is highly recommended that you perform your own measurements against
|
|
310
|
+
In order to rightsize the production environment for your Fastify application,
|
|
311
|
+
it is highly recommended that you perform your own measurements against
|
|
312
312
|
different configurations of the environment, which may
|
|
313
313
|
use real CPU cores, virtual CPU cores (vCPU), or even fractional
|
|
314
314
|
vCPU cores. We will use the term vCPU throughout this
|
|
315
315
|
recommendation to represent any CPU type.
|
|
316
316
|
|
|
317
|
-
Tools such as [k6](https://github.com/grafana/k6)
|
|
317
|
+
Tools such as [k6](https://github.com/grafana/k6)
|
|
318
318
|
or [autocannon](https://github.com/mcollina/autocannon) can be used for
|
|
319
319
|
conducting the necessary performance tests.
|
|
320
320
|
|
|
321
321
|
That said, you may also consider the following as a rule of thumb:
|
|
322
322
|
|
|
323
|
-
* To have the lowest possible latency, 2 vCPU are recommended per app
|
|
324
|
-
instance (e.g., a k8s pod). The second vCPU will mostly be used by the
|
|
325
|
-
garbage collector (GC) and libuv threadpool. This will minimize the latency
|
|
323
|
+
* To have the lowest possible latency, 2 vCPU are recommended per app
|
|
324
|
+
instance (e.g., a k8s pod). The second vCPU will mostly be used by the
|
|
325
|
+
garbage collector (GC) and libuv threadpool. This will minimize the latency
|
|
326
326
|
for your users, as well as the memory usage, as the GC will be run more
|
|
327
327
|
frequently. Also, the main thread won't have to stop to let the GC run.
|
|
328
328
|
|
|
@@ -330,7 +330,7 @@ frequently. Also, the main thread won't have to stop to let the GC run.
|
|
|
330
330
|
requests per second per vCPU available), consider using a smaller amount of vCPUs
|
|
331
331
|
per app instance. It is totally fine to run Node.js applications with 1 vCPU.
|
|
332
332
|
|
|
333
|
-
* You may experiment with an even smaller amount of vCPU, which may provide
|
|
333
|
+
* You may experiment with an even smaller amount of vCPU, which may provide
|
|
334
334
|
even better throughput in certain use-cases. There are reports of API gateway
|
|
335
335
|
solutions working well with 100m-200m vCPU in Kubernetes.
|
|
336
336
|
|
|
@@ -347,7 +347,7 @@ would be exposing metrics endpoints on a separate port,
|
|
|
347
347
|
to prevent public access, when using a reverse proxy or an ingress
|
|
348
348
|
firewall is not an option.
|
|
349
349
|
|
|
350
|
-
It is perfectly fine to spin up several Fastify instances within the same
|
|
351
|
-
Node.js process and run them concurrently, even in high load systems.
|
|
350
|
+
It is perfectly fine to spin up several Fastify instances within the same
|
|
351
|
+
Node.js process and run them concurrently, even in high load systems.
|
|
352
352
|
Each Fastify instance only generates as much load as the traffic it receives,
|
|
353
353
|
plus the memory used for that Fastify instance.
|
|
@@ -36,10 +36,10 @@ snippet of code.
|
|
|
36
36
|
|
|
37
37
|
To integrate with AWS, you have two choices of library:
|
|
38
38
|
|
|
39
|
-
- Using [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify)
|
|
39
|
+
- Using [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify)
|
|
40
40
|
which only adds API Gateway support but has heavy optimizations for fastify.
|
|
41
|
-
- Using [@h4ad/serverless-adapter](https://github.com/H4ad/serverless-adapter)
|
|
42
|
-
which is a little slower as it creates an HTTP request for each AWS event but
|
|
41
|
+
- Using [@h4ad/serverless-adapter](https://github.com/H4ad/serverless-adapter)
|
|
42
|
+
which is a little slower as it creates an HTTP request for each AWS event but
|
|
43
43
|
has support for more AWS services such as: AWS SQS, AWS SNS and others.
|
|
44
44
|
|
|
45
45
|
So you can decide which option is best for you, but you can test both libraries.
|
|
@@ -263,7 +263,7 @@ curl -X POST https://$GOOGLE_REGION-$GOOGLE_PROJECT.cloudfunctions.net/me \
|
|
|
263
263
|
|
|
264
264
|
## Google Firebase Functions
|
|
265
265
|
|
|
266
|
-
Follow this guide if you want to use Fastify as the HTTP framework for
|
|
266
|
+
Follow this guide if you want to use Fastify as the HTTP framework for
|
|
267
267
|
Firebase Functions instead of the vanilla JavaScript router provided with
|
|
268
268
|
`onRequest(async (req, res) => {}`.
|
|
269
269
|
|
|
@@ -280,7 +280,7 @@ const { onRequest } = require("firebase-functions/v2/https")
|
|
|
280
280
|
### Creation of Fastify instance
|
|
281
281
|
|
|
282
282
|
Create the Fastify instance and encapsulate the returned application instance
|
|
283
|
-
in a function which will register routes, await the server's processing of
|
|
283
|
+
in a function which will register routes, await the server's processing of
|
|
284
284
|
plugins, hooks and other settings. As follows:
|
|
285
285
|
|
|
286
286
|
```js
|
package/docs/Guides/Testing.md
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
Testing is one of the most important parts of developing an application. Fastify
|
|
7
7
|
is very flexible when it comes to testing and is compatible with most testing
|
|
8
|
-
frameworks (such as [
|
|
9
|
-
the examples below).
|
|
8
|
+
frameworks (such as [Node Test Runner](https://nodejs.org/api/test.html),
|
|
9
|
+
which is used in the examples below).
|
|
10
10
|
|
|
11
11
|
## Application
|
|
12
12
|
|
|
13
13
|
Let's `cd` into a fresh directory called 'testing-example' and type `npm init
|
|
14
14
|
-y` in our terminal.
|
|
15
15
|
|
|
16
|
-
Run `npm i fastify && npm i
|
|
16
|
+
Run `npm i fastify && npm i pino-pretty -D`
|
|
17
17
|
|
|
18
18
|
### Separating concerns makes testing easy
|
|
19
19
|
|
|
@@ -113,24 +113,25 @@ Now we can replace our `console.log` calls with actual tests!
|
|
|
113
113
|
|
|
114
114
|
In your `package.json` change the "test" script to:
|
|
115
115
|
|
|
116
|
-
`"test": "
|
|
116
|
+
`"test": "node --test --watch"`
|
|
117
117
|
|
|
118
118
|
**app.test.js**:
|
|
119
119
|
|
|
120
120
|
```js
|
|
121
121
|
'use strict'
|
|
122
122
|
|
|
123
|
-
const { test } = require('
|
|
123
|
+
const { test } = require('node:test')
|
|
124
124
|
const build = require('./app')
|
|
125
125
|
|
|
126
126
|
test('requests the "/" route', async t => {
|
|
127
|
+
t.plan(1)
|
|
127
128
|
const app = build()
|
|
128
129
|
|
|
129
130
|
const response = await app.inject({
|
|
130
131
|
method: 'GET',
|
|
131
132
|
url: '/'
|
|
132
133
|
})
|
|
133
|
-
t.
|
|
134
|
+
t.assert.strictEqual(response.statusCode, 200, 'returns a status code of 200')
|
|
134
135
|
})
|
|
135
136
|
```
|
|
136
137
|
|
|
@@ -214,26 +215,26 @@ module.exports = buildFastify
|
|
|
214
215
|
|
|
215
216
|
**test.js**
|
|
216
217
|
```js
|
|
217
|
-
const
|
|
218
|
+
const { test } = require('node:test')
|
|
218
219
|
const buildFastify = require('./app')
|
|
219
220
|
|
|
220
|
-
|
|
221
|
+
test('GET `/` route', t => {
|
|
221
222
|
t.plan(4)
|
|
222
223
|
|
|
223
224
|
const fastify = buildFastify()
|
|
224
225
|
|
|
225
226
|
// At the end of your tests it is highly recommended to call `.close()`
|
|
226
227
|
// to ensure that all connections to external services get closed.
|
|
227
|
-
t.
|
|
228
|
+
t.after(() => fastify.close())
|
|
228
229
|
|
|
229
230
|
fastify.inject({
|
|
230
231
|
method: 'GET',
|
|
231
232
|
url: '/'
|
|
232
233
|
}, (err, response) => {
|
|
233
|
-
t.
|
|
234
|
-
t.
|
|
235
|
-
t.
|
|
236
|
-
t.
|
|
234
|
+
t.assert.ifError(err)
|
|
235
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
236
|
+
t.assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
|
|
237
|
+
t.assert.deepStrictEqual(response.json(), { hello: 'world' })
|
|
237
238
|
})
|
|
238
239
|
})
|
|
239
240
|
```
|
|
@@ -248,11 +249,11 @@ Uses **app.js** from the previous example.
|
|
|
248
249
|
|
|
249
250
|
**test-listen.js** (testing with [`undici`](https://www.npmjs.com/package/undici))
|
|
250
251
|
```js
|
|
251
|
-
const
|
|
252
|
+
const { test } = require('node:test')
|
|
252
253
|
const { Client } = require('undici')
|
|
253
254
|
const buildFastify = require('./app')
|
|
254
255
|
|
|
255
|
-
|
|
256
|
+
test('should work with undici', async t => {
|
|
256
257
|
t.plan(2)
|
|
257
258
|
|
|
258
259
|
const fastify = buildFastify()
|
|
@@ -263,63 +264,64 @@ tap.test('should work with undici', async t => {
|
|
|
263
264
|
'http://localhost:' + fastify.server.address().port, {
|
|
264
265
|
keepAliveTimeout: 10,
|
|
265
266
|
keepAliveMaxTimeout: 10
|
|
266
|
-
}
|
|
267
|
+
}
|
|
267
268
|
)
|
|
268
269
|
|
|
269
|
-
t.
|
|
270
|
+
t.after(() => {
|
|
270
271
|
fastify.close()
|
|
271
272
|
client.close()
|
|
272
273
|
})
|
|
273
274
|
|
|
274
275
|
const response = await client.request({ method: 'GET', path: '/' })
|
|
275
276
|
|
|
276
|
-
t.
|
|
277
|
-
t.
|
|
277
|
+
t.assert.strictEqual(await response.body.text(), '{"hello":"world"}')
|
|
278
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
278
279
|
})
|
|
279
280
|
```
|
|
280
281
|
|
|
281
|
-
Alternatively, starting with Node.js 18,
|
|
282
|
-
[`fetch`](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch)
|
|
282
|
+
Alternatively, starting with Node.js 18,
|
|
283
|
+
[`fetch`](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch)
|
|
283
284
|
may be used without requiring any extra dependencies:
|
|
284
285
|
|
|
285
286
|
**test-listen.js**
|
|
286
287
|
```js
|
|
287
|
-
const
|
|
288
|
+
const { test } = require('node:test')
|
|
288
289
|
const buildFastify = require('./app')
|
|
289
290
|
|
|
290
|
-
|
|
291
|
+
test('should work with fetch', async t => {
|
|
291
292
|
t.plan(3)
|
|
292
293
|
|
|
293
294
|
const fastify = buildFastify()
|
|
294
295
|
|
|
295
|
-
t.
|
|
296
|
+
t.after(() => fastify.close())
|
|
296
297
|
|
|
297
298
|
await fastify.listen()
|
|
298
|
-
|
|
299
|
+
|
|
299
300
|
const response = await fetch(
|
|
300
301
|
'http://localhost:' + fastify.server.address().port
|
|
301
302
|
)
|
|
302
303
|
|
|
303
|
-
t.
|
|
304
|
-
t.
|
|
304
|
+
t.assert.strictEqual(response.status, 200)
|
|
305
|
+
t.assert.strictEqual(
|
|
305
306
|
response.headers.get('content-type'),
|
|
306
307
|
'application/json; charset=utf-8'
|
|
307
308
|
)
|
|
308
|
-
|
|
309
|
+
const jsonResult = await response.json()
|
|
310
|
+
t.assert.strictEqual(jsonResult.hello, 'world')
|
|
309
311
|
})
|
|
310
312
|
```
|
|
311
313
|
|
|
312
314
|
**test-ready.js** (testing with
|
|
313
315
|
[`SuperTest`](https://www.npmjs.com/package/supertest))
|
|
314
316
|
```js
|
|
315
|
-
const
|
|
317
|
+
const { test } = require('node:test')
|
|
316
318
|
const supertest = require('supertest')
|
|
317
319
|
const buildFastify = require('./app')
|
|
318
320
|
|
|
319
|
-
|
|
321
|
+
test('GET `/` route', async (t) => {
|
|
320
322
|
const fastify = buildFastify()
|
|
321
323
|
|
|
322
|
-
t.
|
|
324
|
+
t.after(() => fastify.close())
|
|
323
325
|
|
|
324
326
|
await fastify.ready()
|
|
325
327
|
|
|
@@ -327,21 +329,20 @@ tap.test('GET `/` route', async (t) => {
|
|
|
327
329
|
.get('/')
|
|
328
330
|
.expect(200)
|
|
329
331
|
.expect('Content-Type', 'application/json; charset=utf-8')
|
|
330
|
-
t.
|
|
332
|
+
t.assert.deepStrictEqual(response.body, { hello: 'world' })
|
|
331
333
|
})
|
|
332
334
|
```
|
|
333
335
|
|
|
334
|
-
### How to inspect
|
|
336
|
+
### How to inspect node tests
|
|
335
337
|
1. Isolate your test by passing the `{only: true}` option
|
|
336
338
|
```javascript
|
|
337
339
|
test('should ...', {only: true}, t => ...)
|
|
338
340
|
```
|
|
339
|
-
2. Run `
|
|
341
|
+
2. Run `node --test`
|
|
340
342
|
```bash
|
|
341
|
-
>
|
|
343
|
+
> node --test --test-only --node-arg=--inspect-brk test/<test-file.test.js>
|
|
342
344
|
```
|
|
343
|
-
-
|
|
344
|
-
- `-T` specifies not to timeout (while you're debugging)
|
|
345
|
+
- `--test-only` specifies to run tests with the `only` option enabled
|
|
345
346
|
- `--node-arg=--inspect-brk` will launch the node debugger
|
|
346
347
|
3. In VS Code, create and launch a `Node.js: Attach` debug configuration. No
|
|
347
348
|
modification should be necessary.
|
|
@@ -355,7 +356,7 @@ Now you should be able to step through your test file (and the rest of
|
|
|
355
356
|
Let's `cd` into a fresh directory called 'testing-plugin-example' and type `npm init
|
|
356
357
|
-y` in our terminal.
|
|
357
358
|
|
|
358
|
-
Run `npm i fastify fastify-plugin
|
|
359
|
+
Run `npm i fastify fastify-plugin`
|
|
359
360
|
|
|
360
361
|
**plugin/myFirstPlugin.js**:
|
|
361
362
|
|
|
@@ -376,16 +377,16 @@ A basic example of a Plugin. See [Plugin Guide](./Plugins-Guide.md)
|
|
|
376
377
|
|
|
377
378
|
```js
|
|
378
379
|
const Fastify = require("fastify");
|
|
379
|
-
const
|
|
380
|
+
const { test } = require("node:test");
|
|
380
381
|
const myPlugin = require("../plugin/myFirstPlugin");
|
|
381
382
|
|
|
382
|
-
|
|
383
|
+
test("Test the Plugin Route", async t => {
|
|
383
384
|
// Create a mock fastify application to test the plugin
|
|
384
385
|
const fastify = Fastify()
|
|
385
386
|
|
|
386
387
|
fastify.register(myPlugin)
|
|
387
388
|
|
|
388
|
-
// Add an endpoint of your choice
|
|
389
|
+
// Add an endpoint of your choice
|
|
389
390
|
fastify.get("/", async (request, reply) => {
|
|
390
391
|
return ({ message: request.helloRequest })
|
|
391
392
|
})
|
|
@@ -395,7 +396,7 @@ tap.test("Test the Plugin Route", async t => {
|
|
|
395
396
|
method: "GET",
|
|
396
397
|
url: "/"
|
|
397
398
|
})
|
|
398
|
-
|
|
399
|
+
|
|
399
400
|
console.log('status code: ', fastifyResponse.statusCode)
|
|
400
401
|
console.log('body: ', fastifyResponse.body)
|
|
401
402
|
})
|
|
@@ -412,18 +413,18 @@ Now we can replace our `console.log` calls with actual tests!
|
|
|
412
413
|
|
|
413
414
|
In your `package.json` change the "test" script to:
|
|
414
415
|
|
|
415
|
-
`"test": "
|
|
416
|
+
`"test": "node --test --watch"`
|
|
416
417
|
|
|
417
|
-
Create the
|
|
418
|
+
Create the test for the endpoint.
|
|
418
419
|
|
|
419
420
|
**test/myFirstPlugin.test.js**:
|
|
420
421
|
|
|
421
422
|
```js
|
|
422
423
|
const Fastify = require("fastify");
|
|
423
|
-
const
|
|
424
|
+
const { test } = require("node:test");
|
|
424
425
|
const myPlugin = require("../plugin/myFirstPlugin");
|
|
425
426
|
|
|
426
|
-
|
|
427
|
+
test("Test the Plugin Route", async t => {
|
|
427
428
|
// Specifies the number of test
|
|
428
429
|
t.plan(2)
|
|
429
430
|
|
|
@@ -439,9 +440,9 @@ tap.test("Test the Plugin Route", async t => {
|
|
|
439
440
|
method: "GET",
|
|
440
441
|
url: "/"
|
|
441
442
|
})
|
|
442
|
-
|
|
443
|
-
t.
|
|
444
|
-
t.
|
|
443
|
+
|
|
444
|
+
t.assert.strictEqual(fastifyResponse.statusCode, 200)
|
|
445
|
+
t.assert.deepStrictEqual(JSON.parse(fastifyResponse.body), { message: "Hello World" })
|
|
445
446
|
})
|
|
446
447
|
```
|
|
447
448
|
|
|
@@ -453,10 +454,10 @@ Test the ```.decorate()``` and ```.decorateRequest()```.
|
|
|
453
454
|
|
|
454
455
|
```js
|
|
455
456
|
const Fastify = require("fastify");
|
|
456
|
-
const
|
|
457
|
+
const { test }= require("node:test");
|
|
457
458
|
const myPlugin = require("../plugin/myFirstPlugin");
|
|
458
459
|
|
|
459
|
-
|
|
460
|
+
test("Test the Plugin Route", async t => {
|
|
460
461
|
t.plan(5)
|
|
461
462
|
const fastify = Fastify()
|
|
462
463
|
|
|
@@ -464,9 +465,9 @@ tap.test("Test the Plugin Route", async t => {
|
|
|
464
465
|
|
|
465
466
|
fastify.get("/", async (request, reply) => {
|
|
466
467
|
// Testing the fastify decorators
|
|
467
|
-
t.
|
|
468
|
-
t.ok(request.helloRequest, "Hello World")
|
|
469
|
-
t.ok(fastify.helloInstance, "Hello Fastify Instance")
|
|
468
|
+
t.assert.ifError(request.helloRequest)
|
|
469
|
+
t.assert.ok(request.helloRequest, "Hello World")
|
|
470
|
+
t.assert.ok(fastify.helloInstance, "Hello Fastify Instance")
|
|
470
471
|
return ({ message: request.helloRequest })
|
|
471
472
|
})
|
|
472
473
|
|
|
@@ -474,7 +475,7 @@ tap.test("Test the Plugin Route", async t => {
|
|
|
474
475
|
method: "GET",
|
|
475
476
|
url: "/"
|
|
476
477
|
})
|
|
477
|
-
t.
|
|
478
|
-
t.
|
|
478
|
+
t.assert.strictEqual(fastifyResponse.statusCode, 200)
|
|
479
|
+
t.assert.deepStrictEqual(JSON.parse(fastifyResponse.body), { message: "Hello World" })
|
|
479
480
|
})
|
|
480
|
-
```
|
|
481
|
+
```
|
|
@@ -60,10 +60,10 @@ A plugin without tests will not be accepted to the ecosystem list. A lack of
|
|
|
60
60
|
tests does not inspire trust nor guarantee that the code will continue to work
|
|
61
61
|
among different versions of its dependencies.
|
|
62
62
|
|
|
63
|
-
We do not enforce any testing library. We use [`
|
|
63
|
+
We do not enforce any testing library. We use [`node:test`](https://nodejs.org/api/test.html)
|
|
64
64
|
since it offers out-of-the-box parallel testing and code coverage, but it is up
|
|
65
65
|
to you to choose your library of preference.
|
|
66
|
-
We highly recommend you read the [Plugin Testing](./Testing.md#plugins) to
|
|
66
|
+
We highly recommend you read the [Plugin Testing](./Testing.md#plugins) to
|
|
67
67
|
learn about how to test your plugins.
|
|
68
68
|
|
|
69
69
|
## Code Linter
|
|
@@ -10,9 +10,9 @@ Whereas exhaustive type narrowing checks normally rely on `never` to represent
|
|
|
10
10
|
an unreachable state, reduction in type provider interfaces should only be done
|
|
11
11
|
up to `unknown`.
|
|
12
12
|
|
|
13
|
-
The reasoning is that certain methods of `FastifyInstance` are
|
|
14
|
-
contravariant on `TypeProvider`, which can lead to TypeScript surfacing
|
|
15
|
-
assignability issues unless the custom type provider interface is
|
|
13
|
+
The reasoning is that certain methods of `FastifyInstance` are
|
|
14
|
+
contravariant on `TypeProvider`, which can lead to TypeScript surfacing
|
|
15
|
+
assignability issues unless the custom type provider interface is
|
|
16
16
|
substitutable with `FastifyTypeProviderDefault`.
|
|
17
17
|
|
|
18
18
|
For example, `FastifyTypeProviderDefault` will not be assignable to the following:
|
|
@@ -53,7 +53,7 @@ fastify.addContentTypeParser(['text/xml', 'application/xml'], function (request,
|
|
|
53
53
|
|
|
54
54
|
// Async is also supported in Node versions >= 8.0.0
|
|
55
55
|
fastify.addContentTypeParser('application/jsoff', async function (request, payload) {
|
|
56
|
-
|
|
56
|
+
const res = await jsoffParserAsync(payload)
|
|
57
57
|
|
|
58
58
|
return res
|
|
59
59
|
})
|
|
@@ -181,7 +181,7 @@ limit is exceeded the custom parser will not be invoked.
|
|
|
181
181
|
```js
|
|
182
182
|
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
|
|
183
183
|
try {
|
|
184
|
-
|
|
184
|
+
const json = JSON.parse(body)
|
|
185
185
|
done(null, json)
|
|
186
186
|
} catch (err) {
|
|
187
187
|
err.statusCode = 400
|
|
@@ -206,7 +206,7 @@ There are some cases where you need to catch all requests regardless of their
|
|
|
206
206
|
content type. With Fastify, you can just use the `'*'` content type.
|
|
207
207
|
```js
|
|
208
208
|
fastify.addContentTypeParser('*', function (request, payload, done) {
|
|
209
|
-
|
|
209
|
+
let data = ''
|
|
210
210
|
payload.on('data', chunk => { data += chunk })
|
|
211
211
|
payload.on('end', () => {
|
|
212
212
|
done(null, data)
|
|
@@ -266,7 +266,7 @@ only on those that don't have a specific one, you should call the
|
|
|
266
266
|
fastify.removeAllContentTypeParsers()
|
|
267
267
|
|
|
268
268
|
fastify.addContentTypeParser('*', function (request, payload, done) {
|
|
269
|
-
|
|
269
|
+
const data = ''
|
|
270
270
|
payload.on('data', chunk => { data += chunk })
|
|
271
271
|
payload.on('end', () => {
|
|
272
272
|
done(null, data)
|
|
@@ -59,7 +59,7 @@ close as possible to the value intended to be set dynamically in the future.
|
|
|
59
59
|
Initialize a decorator as a `''` if the intended value is a string, and as
|
|
60
60
|
`null` if it will be an object or a function.
|
|
61
61
|
|
|
62
|
-
Remember this example works only with value types as reference types will
|
|
62
|
+
Remember this example works only with value types as reference types will
|
|
63
63
|
thrown and error during the fastify startup. See [decorateRequest](#decorate-request).
|
|
64
64
|
|
|
65
65
|
See [JavaScript engine fundamentals: Shapes and Inline
|
|
@@ -109,7 +109,7 @@ fastify.decorate('db', new DbConnection())
|
|
|
109
109
|
fastify.get('/', async function (request, reply) {
|
|
110
110
|
// using return
|
|
111
111
|
return { hello: await this.db.query('world') }
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
// or
|
|
114
114
|
// using reply.send()
|
|
115
115
|
reply.send({ hello: await this.db.query('world') })
|
package/docs/Reference/Errors.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**Table of contents**
|
|
7
7
|
- [Errors](#errors)
|
|
8
|
-
- [Error Handling In Node.js](#error-handling-in-
|
|
8
|
+
- [Error Handling In Node.js](#error-handling-in-nodejs)
|
|
9
9
|
- [Uncaught Errors](#uncaught-errors)
|
|
10
10
|
- [Catching Errors In Promises](#catching-errors-in-promises)
|
|
11
11
|
- [Errors In Fastify](#errors-in-fastify)
|
|
@@ -178,13 +178,13 @@ When utilizing Fastify's custom error handling through [`setErrorHandler`](./Ser
|
|
|
178
178
|
you should be aware of how errors are propagated between custom and default
|
|
179
179
|
error handlers.
|
|
180
180
|
|
|
181
|
-
If a plugin's error handler re-throws an error, and the error is not an
|
|
181
|
+
If a plugin's error handler re-throws an error, and the error is not an
|
|
182
182
|
instance of [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
|
183
183
|
(as seen in the `/bad` route in the following example), it will not propagate
|
|
184
184
|
to the parent context error handler. Instead, it will be caught by the default
|
|
185
185
|
error handler.
|
|
186
186
|
|
|
187
|
-
To ensure consistent error handling, it is recommended to throw instances of
|
|
187
|
+
To ensure consistent error handling, it is recommended to throw instances of
|
|
188
188
|
`Error`. For instance, in the following example, replacing `throw 'foo'` with
|
|
189
189
|
`throw new Error('foo')` in the `/bad` route ensures that errors propagate through
|
|
190
190
|
the custom error handling chain as intended. This practice helps avoid potential
|
package/docs/Reference/Hooks.md
CHANGED
|
@@ -107,7 +107,7 @@ 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
|
-
**Notice:** The size of the returned stream is checked to not exceed the limit
|
|
110
|
+
**Notice:** 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
|
|
@@ -256,8 +256,8 @@ 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
|
-
**Note:** setting `disableRequestLogging` to `true` will disable any error log
|
|
260
|
-
inside the `onResponse` hook. In this case use `try - catch` to log errors.
|
|
259
|
+
**Note:** setting `disableRequestLogging` to `true` will disable any error log
|
|
260
|
+
inside the `onResponse` hook. In this case use `try - catch` to log errors.
|
|
261
261
|
|
|
262
262
|
### onTimeout
|
|
263
263
|
|
|
@@ -428,8 +428,8 @@ fastify.addHook('onReady', async function () {
|
|
|
428
428
|
|
|
429
429
|
### onListen
|
|
430
430
|
|
|
431
|
-
Triggered when the server starts listening for requests. The hooks run one
|
|
432
|
-
after another. If a hook function causes an error, it is logged and
|
|
431
|
+
Triggered when the server starts listening for requests. The hooks run one
|
|
432
|
+
after another. If a hook function causes an error, it is logged and
|
|
433
433
|
ignored, allowing the queue of hooks to continue. Hook functions accept one
|
|
434
434
|
argument: a callback, `done`, to be invoked after the hook function is
|
|
435
435
|
complete. Hook functions are invoked with `this` bound to the associated
|
|
@@ -451,7 +451,7 @@ fastify.addHook('onListen', async function () {
|
|
|
451
451
|
})
|
|
452
452
|
```
|
|
453
453
|
|
|
454
|
-
> **Note**
|
|
454
|
+
> **Note**
|
|
455
455
|
> This hook will not run when the server is started using `fastify.inject()` or `fastify.ready()`
|
|
456
456
|
|
|
457
457
|
### onClose
|
|
@@ -462,7 +462,7 @@ HTTP requests have been completed.
|
|
|
462
462
|
It is useful when [plugins](./Plugins.md) need a "shutdown" event, for example,
|
|
463
463
|
to close an open connection to a database.
|
|
464
464
|
|
|
465
|
-
The hook function takes the Fastify instance as a first argument,
|
|
465
|
+
The hook function takes the Fastify instance as a first argument,
|
|
466
466
|
and a `done` callback for synchronous hook functions.
|
|
467
467
|
```js
|
|
468
468
|
// callback style
|
package/docs/Reference/LTS.md
CHANGED
|
@@ -48,6 +48,12 @@ A "month" is defined as 30 consecutive days.
|
|
|
48
48
|
> dependency as `"fastify": "~3.15.x"`. This will leave your application
|
|
49
49
|
> vulnerable, so please use with caution.
|
|
50
50
|
|
|
51
|
+
### Security Support Beyond LTS
|
|
52
|
+
|
|
53
|
+
Fastify's partner, HeroDevs, provides commercial security support through the
|
|
54
|
+
OpenJS Ecosystem Sustainability Program for versions of Fastify that are EOL.
|
|
55
|
+
For more information, see their [Never Ending Support][hd-link] service.
|
|
56
|
+
|
|
51
57
|
### Schedule
|
|
52
58
|
|
|
53
59
|
`<a id="lts-schedule"></a>`
|
|
@@ -81,3 +87,5 @@ Using [yarn](https://yarnpkg.com/) might require passing the `--ignore-engines`
|
|
|
81
87
|
flag.
|
|
82
88
|
|
|
83
89
|
[semver]: https://semver.org/
|
|
90
|
+
|
|
91
|
+
[hd-link]: https://www.herodevs.com/support/fastify-nes?utm_source=fastify&utm_medium=link&utm_campaign=eol_support_fastify
|
|
@@ -204,15 +204,16 @@ on serializers for more information.
|
|
|
204
204
|
*Any logger other than Pino will ignore this option.*
|
|
205
205
|
|
|
206
206
|
You can also supply your own logger instance. Instead of passing configuration
|
|
207
|
-
options, pass the instance
|
|
208
|
-
interface; that is, it must have the following methods:
|
|
209
|
-
`debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a
|
|
207
|
+
options, pass the instance as `loggerInstance`. The logger you supply must
|
|
208
|
+
conform to the Pino interface; that is, it must have the following methods:
|
|
209
|
+
`info`, `error`, `debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a
|
|
210
|
+
string property `level`.
|
|
210
211
|
|
|
211
212
|
Example:
|
|
212
213
|
|
|
213
214
|
```js
|
|
214
215
|
const log = require('pino')({ level: 'info' })
|
|
215
|
-
const fastify = require('fastify')({
|
|
216
|
+
const fastify = require('fastify')({ loggerInstance: log })
|
|
216
217
|
|
|
217
218
|
log.info('does not have request information')
|
|
218
219
|
|