fastify 4.0.0-rc.5 → 4.0.2

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 (41) hide show
  1. package/.markdownlint-cli2.yaml +22 -0
  2. package/GOVERNANCE.md +30 -20
  3. package/PROJECT_CHARTER.md +48 -17
  4. package/README.md +164 -77
  5. package/SECURITY.md +55 -44
  6. package/build/build-error-serializer.js +12 -7
  7. package/docs/Guides/Benchmarking.md +2 -0
  8. package/docs/Guides/Delay-Accepting-Requests.md +98 -90
  9. package/docs/Guides/Ecosystem.md +48 -38
  10. package/docs/Guides/Index.md +2 -0
  11. package/docs/Guides/Migration-Guide-V3.md +1 -1
  12. package/docs/Guides/Migration-Guide-V4.md +55 -0
  13. package/docs/Guides/Plugins-Guide.md +3 -3
  14. package/docs/Guides/Prototype-Poisoning.md +1 -1
  15. package/docs/Guides/Recommendations.md +2 -2
  16. package/docs/Guides/Serverless.md +17 -16
  17. package/docs/Guides/Write-Plugin.md +3 -3
  18. package/docs/Reference/ContentTypeParser.md +17 -13
  19. package/docs/Reference/Errors.md +6 -5
  20. package/docs/Reference/Middleware.md +3 -3
  21. package/docs/Reference/Plugins.md +8 -6
  22. package/docs/Reference/Reply.md +30 -16
  23. package/docs/Reference/Request.md +3 -3
  24. package/docs/Reference/Routes.md +113 -38
  25. package/docs/Reference/Server.md +109 -72
  26. package/docs/Reference/Type-Providers.md +28 -8
  27. package/docs/Reference/TypeScript.md +12 -6
  28. package/docs/Reference/Validation-and-Serialization.md +47 -35
  29. package/fastify.js +1 -1
  30. package/lib/error-serializer.js +32 -204
  31. package/lib/pluginUtils.js +10 -0
  32. package/lib/reply.js +1 -1
  33. package/lib/schemas.js +3 -0
  34. package/lib/validation.js +1 -1
  35. package/package.json +6 -4
  36. package/test/build/error-serializer.test.js +28 -0
  37. package/test/{internals → build}/version.test.js +1 -1
  38. package/test/plugin.test.js +32 -0
  39. package/test/reply-error.test.js +7 -1
  40. package/test/schema-serialization.test.js +30 -0
  41. package/docs/Migration-Guide-V4.md +0 -12
@@ -129,7 +129,11 @@ fastify.get('/', async function (req, rep) {
129
129
  Sets a response header. If the value is omitted or undefined, it is coerced to
130
130
  `''`.
131
131
 
132
- > Note: the header's value must be properly encoded using [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI) or similar modules such as [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid characters will result in a 500 `TypeError` response.
132
+ > Note: the header's value must be properly encoded using
133
+ > [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
134
+ > or similar modules such as
135
+ > [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid characters
136
+ > will result in a 500 `TypeError` response.
133
137
 
134
138
  For more information, see
135
139
  [`http.ServerResponse#setHeader`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_response_setheader_name_value).
@@ -208,11 +212,16 @@ Returns a boolean indicating if the specified header has been set.
208
212
  ### .trailer(key, function)
209
213
  <a id="trailer"></a>
210
214
 
211
- Sets a response trailer. Trailer is usually used when you need a header that requires heavy resources to be sent after the `data`, for example, `Server-Timing` and `Etag`. It can ensure the client receives the response data as soon as possible.
215
+ Sets a response trailer. Trailer is usually used when you need a header that
216
+ requires heavy resources to be sent after the `data`, for example,
217
+ `Server-Timing` and `Etag`. It can ensure the client receives the response data
218
+ as soon as possible.
212
219
 
213
- *Note: The header `Transfer-Encoding: chunked` will be added once you use the trailer. It is a hard requirement for using trailer in Node.js.*
220
+ *Note: The header `Transfer-Encoding: chunked` will be added once you use the
221
+ trailer. It is a hard requirement for using trailer in Node.js.*
214
222
 
215
- *Note: Currently, the computation function only supports synchronous function. That means `async-await` and `promise` are not supported.*
223
+ *Note: Currently, the computation function only supports synchronous function.
224
+ That means `async-await` and `promise` are not supported.*
216
225
 
217
226
  ```js
218
227
  reply.trailer('server-timing', function() {
@@ -254,7 +263,11 @@ reply.getTrailer('server-timing') // undefined
254
263
  Redirects a request to the specified URL, the status code is optional, default
255
264
  to `302` (if status code is not already set by calling `code`).
256
265
 
257
- > Note: the input URL must be properly encoded using [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI) or similar modules such as [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid URLs will result in a 500 `TypeError` response.
266
+ > Note: the input URL must be properly encoded using
267
+ > [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
268
+ > or similar modules such as
269
+ > [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid URLs will
270
+ > result in a 500 `TypeError` response.
258
271
 
259
272
  Example (no `reply.code()` call) sets status code to `302` and redirects to
260
273
  `/home`
@@ -310,7 +323,8 @@ Sets the content type for the response. This is a shortcut for
310
323
  ```js
311
324
  reply.type('text/html')
312
325
  ```
313
- If the `Content-Type` has a JSON subtype, and the charset parameter is not set, `utf-8` will be used as the charset by default.
326
+ If the `Content-Type` has a JSON subtype, and the charset parameter is not set,
327
+ `utf-8` will be used as the charset by default.
314
328
 
315
329
  ### .serializer(func)
316
330
  <a id="serializer"></a>
@@ -366,22 +380,22 @@ Another example of the misuse of `Reply.raw` is explained in
366
380
  <a id="sent"></a>
367
381
 
368
382
  As the name suggests, `.sent` is a property to indicate if a response has been
369
- sent via `reply.send()`.
370
- It will also be `true` in case `reply.hijack()` was used.
383
+ sent via `reply.send()`. It will also be `true` in case `reply.hijack()` was
384
+ used.
371
385
 
372
386
  In case a route handler is defined as an async function or it returns a promise,
373
387
  it is possible to call `reply.hijack()` to indicate that the automatic
374
388
  invocation of `reply.send()` once the handler promise resolve should be skipped.
375
- By calling `reply.hijack()`, an application claims full responsibility for
376
- the low-level request and response. Moreover, hooks will not be invoked.
389
+ By calling `reply.hijack()`, an application claims full responsibility for the
390
+ low-level request and response. Moreover, hooks will not be invoked.
377
391
 
378
- *Modifying the `.sent` property directly is deprecated. Please use the aforementioned
379
- `.hijack()` method to achieve the same effect.*
392
+ *Modifying the `.sent` property directly is deprecated. Please use the
393
+ aforementioned `.hijack()` method to achieve the same effect.*
380
394
 
381
395
  <a name="hijack"></a>
382
396
  ### .hijack()
383
- Sometimes you might need to halt the execution of the normal request lifecycle and
384
- handle sending the response manually.
397
+ Sometimes you might need to halt the execution of the normal request lifecycle
398
+ and handle sending the response manually.
385
399
 
386
400
  To achieve this, Fastify provides the `reply.hijack()` method that can be called
387
401
  during the request lifecycle (At any point before `reply.send()` is called), and
@@ -561,8 +575,8 @@ fastify.setNotFoundHandler(function (request, reply) {
561
575
  <a id="payload-type"></a>
562
576
 
563
577
  The type of the sent payload (after serialization and going through any
564
- [`onSend` hooks](./Hooks.md#onsend)) must be one of the following
565
- types, otherwise, an error will be thrown:
578
+ [`onSend` hooks](./Hooks.md#onsend)) must be one of the following types,
579
+ otherwise, an error will be thrown:
566
580
 
567
581
  - `string`
568
582
  - `Buffer`
@@ -13,7 +13,7 @@ Request is a core Fastify object containing the following fields:
13
13
  - [`headers`](#headers) - the headers getter and setter
14
14
  - `raw` - the incoming HTTP request from Node core
15
15
  - `server` - The Fastify server instance, scoped to the current [encapsulation
16
- >>>>>>> main:docs/Reference/Request.md
16
+ context](./Encapsulation.md)
17
17
  - `id` - the request ID
18
18
  - `log` - the logger instance of the incoming request
19
19
  - `ip` - the IP address of the incoming request
@@ -55,8 +55,8 @@ This operation will add to the request headers the new values that can be read
55
55
  calling `request.headers.bar`. Moreover, you can still access the standard
56
56
  request's headers with the `request.raw.headers` property.
57
57
 
58
- > Note: For performance reason on `not found` route, you may see that we will add
59
- an extra property `Symbol('fastify.RequestAcceptVersion')` on the headers.
58
+ > Note: For performance reason on `not found` route, you may see that we will
59
+ add an extra property `Symbol('fastify.RequestAcceptVersion')` on the headers.
60
60
 
61
61
  ```js
62
62
  fastify.post('/:params', options, function (request, reply) {
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## Routes
4
4
 
5
- The route methods will configure the endpoints of your application. You have
6
- two ways to declare a route with Fastify: the shorthand method and the full
5
+ The route methods will configure the endpoints of your application. You have two
6
+ ways to declare a route with Fastify: the shorthand method and the full
7
7
  declaration.
8
8
 
9
9
  - [Full declaration](#full-declaration)
@@ -13,7 +13,8 @@ declaration.
13
13
  - [Async Await](#async-await)
14
14
  - [Promise resolution](#promise-resolution)
15
15
  - [Route Prefixing](#route-prefixing)
16
- - [Handling of / route inside prefixed plugins](#handling-of--route-inside-prefixed-plugins)
16
+ - [Handling of / route inside prefixed
17
+ plugins](#handling-of--route-inside-prefixed-plugins)
17
18
  - [Custom Log Level](#custom-log-level)
18
19
  - [Custom Log Serializer](#custom-log-serializer)
19
20
  - [Config](#config)
@@ -52,8 +53,9 @@ fastify.route(options)
52
53
  instance option. If you want a custom `HEAD` handler without disabling this
53
54
  option, make sure to define it before the `GET` route.
54
55
  * `attachValidation`: attach `validationError` to request, if there is a schema
55
- validation error, instead of sending the error to the error handler.
56
- The default [error format](https://ajv.js.org/api.html#error-objects) is the Ajv one.
56
+ validation error, instead of sending the error to the error handler. The
57
+ default [error format](https://ajv.js.org/api.html#error-objects) is the Ajv
58
+ one.
57
59
  * `onRequest(request, reply, done)`: a [function](./Hooks.md#onrequest) called
58
60
  as soon as a request is received, it could also be an array of functions.
59
61
  * `preParsing(request, reply, done)`: a [function](./Hooks.md#preparsing) called
@@ -114,7 +116,8 @@ fastify.route(options)
114
116
  * `slash`: Will register only `/prefix/`.
115
117
  * `no-slash`: Will register only `/prefix`.
116
118
 
117
- Note: this option does not override `ignoreTrailingSlash` in [Server](./Server.md) configuration.
119
+ Note: this option does not override `ignoreTrailingSlash` in
120
+ [Server](./Server.md) configuration.
118
121
 
119
122
  * `request` is defined in [Request](./Request.md).
120
123
 
@@ -227,35 +230,66 @@ checked before parametric and wildcard.*
227
230
 
228
231
  ```js
229
232
  // parametric
230
- fastify.get('/example/:userId', (request, reply) => {})
231
- fastify.get('/example/:userId/:secretToken', (request, reply) => {})
233
+ fastify.get('/example/:userId', function (request, reply) {
234
+ // curl ${app-url}/example/12345
235
+ // userId === '12345'
236
+ const { userId } = request.params;
237
+ // your code here
238
+ })
239
+ fastify.get('/example/:userId/:secretToken', function (request, reply) {
240
+ // curl ${app-url}/example/12345/abc.zHi
241
+ // userId === '12345'
242
+ // secretToken === 'abc.zHi'
243
+ const { userId, secretToken } = request.params;
244
+ // your code here
245
+ })
232
246
 
233
247
  // wildcard
234
- fastify.get('/example/*', (request, reply) => {})
248
+ fastify.get('/example/*', function (request, reply) {})
235
249
  ```
236
250
 
237
- Regular expression routes are supported as well, but be aware that you have to escape slashes. Take note that RegExp is also very expensive in terms of performance!
251
+ Regular expression routes are supported as well, but be aware that you have to
252
+ escape slashes. Take note that RegExp is also very expensive in terms of
253
+ performance!
238
254
  ```js
239
255
  // parametric with regexp
240
- fastify.get('/example/:file(^\\d+).png', (request, reply) => {})
256
+ fastify.get('/example/:file(^\\d+).png', function (request, reply) {
257
+ // curl ${app-url}/example/12345.png
258
+ // file === '12345'
259
+ const { file } = request.params;
260
+ // your code here
261
+ })
241
262
  ```
242
263
 
243
264
  It is possible to define more than one parameter within the same couple of slash
244
265
  ("/"). Such as:
245
266
  ```js
246
- fastify.get('/example/near/:lat-:lng/radius/:r', (request, reply) => {})
267
+ fastify.get('/example/near/:lat-:lng/radius/:r', function (request, reply) {
268
+ // curl ${app-url}/example/near/15°N-30°E/radius/20
269
+ // lat === "15°N"
270
+ // lng === "30°E"
271
+ // r ==="20"
272
+ const { lat, lng, r } = request.params;
273
+ // your code here
274
+ })
247
275
  ```
248
276
  *Remember in this case to use the dash ("-") as parameters separator.*
249
277
 
250
278
  Finally, it is possible to have multiple parameters with RegExp:
251
279
  ```js
252
- fastify.get('/example/at/:hour(^\\d{2})h:minute(^\\d{2})m', (request, reply) => {})
280
+ fastify.get('/example/at/:hour(^\\d{2})h:minute(^\\d{2})m', function (request, reply) {
281
+ // curl ${app-url}/example/at/08h24m
282
+ // hour === "08"
283
+ // minute === "24"
284
+ const { hour, minute } = request.params;
285
+ // your code here
286
+ })
253
287
  ```
254
288
  In this case as parameter separator it is possible to use whatever character is
255
289
  not matched by the regular expression.
256
290
 
257
- Having a route with multiple parameters may negatively affect performance,
258
- so prefer a single parameter approach whenever possible, especially on routes that
291
+ Having a route with multiple parameters may negatively affect performance, so
292
+ prefer a single parameter approach whenever possible, especially on routes that
259
293
  are on the hot path of your application. If you are interested in how we handle
260
294
  the routing, check out [find-my-way](https://github.com/delvedor/find-my-way).
261
295
 
@@ -280,8 +314,8 @@ fastify.get('/', options, async function (request, reply) {
280
314
  As you can see, we are not calling `reply.send` to send back the data to the
281
315
  user. You just need to return the body and you are done!
282
316
 
283
- If you need it you can also send back the data to the user with `reply.send`.
284
- In this case do not forget to `return reply` or `await reply` in your `async`
317
+ If you need it you can also send back the data to the user with `reply.send`. In
318
+ this case do not forget to `return reply` or `await reply` in your `async`
285
319
  handler or you will introduce a race condition in certain situations.
286
320
 
287
321
  ```js
@@ -320,22 +354,22 @@ fastify.get('/', options, async function (request, reply) {
320
354
  first one that happens takes precedence, the second value will be discarded,
321
355
  and a *warn* log will also be emitted because you tried to send a response
322
356
  twice.
323
- * Calling `reply.send()` outside of the promise is possible but requires
324
- special attention. For more details read
325
- [promise-resolution](#promise-resolution).
357
+ * Calling `reply.send()` outside of the promise is possible but requires special
358
+ attention. For more details read [promise-resolution](#promise-resolution).
326
359
  * You cannot return `undefined`. For more details read
327
360
  [promise-resolution](#promise-resolution).
328
361
 
329
362
  ### Promise resolution
330
363
  <a id="promise-resolution"></a>
331
364
 
332
- If your handler is an `async` function or returns a promise, you should be aware of
333
- the special behavior that is necessary to support the callback and promise
365
+ If your handler is an `async` function or returns a promise, you should be aware
366
+ of the special behavior that is necessary to support the callback and promise
334
367
  control-flow. When the handler's promise is resolved, the reply will be
335
368
  automatically sent with its value unless you explicitly await or return `reply`
336
369
  in your handler.
337
370
 
338
- 1. If you want to use `async/await` or promises but respond with a value with `reply.send`:
371
+ 1. If you want to use `async/await` or promises but respond with a value with
372
+ `reply.send`:
339
373
  - **Do** `return reply` / `await reply`.
340
374
  - **Do not** forget to call `reply.send`.
341
375
  2. If you want to use `async/await` or promises:
@@ -343,9 +377,9 @@ in your handler.
343
377
  - **Do** return the value that you want to send.
344
378
 
345
379
  In this way, we can support both `callback-style` and `async-await`, with the
346
- minimum trade-off. Despite so much freedom we highly recommend going with
347
- only one style because error handling should be handled in a consistent way
348
- within your application.
380
+ minimum trade-off. Despite so much freedom we highly recommend going with only
381
+ one style because error handling should be handled in a consistent way within
382
+ your application.
349
383
 
350
384
  **Notice**: Every async function returns a promise by itself.
351
385
 
@@ -392,14 +426,55 @@ Now your clients will have access to the following routes:
392
426
  - `/v2/user`
393
427
 
394
428
  You can do this as many times as you want, it also works for nested `register`,
395
- and route parameters are supported as well. Be aware that if you use
396
- [`fastify-plugin`](https://github.com/fastify/fastify-plugin) this option will
397
- not work.
429
+ and route parameters are supported as well.
430
+
431
+ In case you want to use prefix for all of your routes, you can put them inside a
432
+ plugin:
433
+
434
+ ```js
435
+ const fastify = require('fastify')()
436
+
437
+ const route = {
438
+ method: 'POST',
439
+ url: '/login',
440
+ handler: () => {},
441
+ schema: {},
442
+ }
443
+
444
+ fastify.register(function(app, _, done) {
445
+ app.get('/users', () => {})
446
+ app.route(route)
447
+
448
+ done()
449
+ }, { prefix: '/v1' }) // global route prefix
450
+
451
+ await fastify.listen({ port: 0 })
452
+ ```
453
+
454
+ ### Route Prefixing and fastify-plugin
455
+ <a id="fastify-plugin"></a>
456
+
457
+ Be aware that if you use
458
+ [`fastify-plugin`](https://github.com/fastify/fastify-plugin) for wrapping your
459
+ routes, this option will not work. You can still make it work by wrapping a
460
+ plugin in a plugin, e. g.:
461
+ ```js
462
+ const fp = require('fastify-plugin')
463
+ const routes = require('./lib/routes')
464
+
465
+ module.exports = fp(async function (app, opts) {
466
+ app.register(routes, {
467
+ prefix: '/v1',
468
+ })
469
+ }, {
470
+ name: 'my-routes'
471
+ })
472
+ ```
398
473
 
399
474
  #### Handling of / route inside prefixed plugins
400
475
 
401
- The `/` route has different behavior depending on if the prefix ends with `/`
402
- or not. As an example, if we consider a prefix `/something/`, adding a `/` route
476
+ The `/` route has different behavior depending on if the prefix ends with `/` or
477
+ not. As an example, if we consider a prefix `/something/`, adding a `/` route
403
478
  will only match `/something/`. If we consider a prefix `/something`, adding a
404
479
  `/` route will match both `/something` and `/something/`.
405
480
 
@@ -408,8 +483,8 @@ See the `prefixTrailingSlash` route option above to change this behavior.
408
483
  ### Custom Log Level
409
484
  <a id="custom-log-level"></a>
410
485
 
411
- You might need different log levels in your routes; Fastify
412
- achieves this in a very straightforward way.
486
+ You might need different log levels in your routes; Fastify achieves this in a
487
+ very straightforward way.
413
488
 
414
489
  You just need to pass the option `logLevel` to the plugin option or the route
415
490
  option with the
@@ -540,7 +615,7 @@ You can provide a `version` key in the `constraints` option to a route.
540
615
  Versioned routes allow you to declare multiple handlers for the same HTTP route
541
616
  path, which will then be matched according to each request's `Accept-Version`
542
617
  header. The `Accept-Version` header value should follow the
543
- [semver](http://semver.org/) specification, and routes should be declared with
618
+ [semver](https://semver.org/) specification, and routes should be declared with
544
619
  exact semver versions for matching.
545
620
 
546
621
  Fastify will require a request `Accept-Version` header to be set if the route
@@ -659,9 +734,9 @@ fastify.route({
659
734
  Fastify will check the HTTP version of every request, based on configuration
660
735
  options ([http2](./Server.md#http2), [https](./Server.md#https), and
661
736
  [serverFactory](./Server.md#serverfactory)), to determine if it matches one or
662
- all of the > following versions: `2.0`, `1.1`, and `1.0`. If Fastify receives
663
- a different HTTP version in the request it will return a
664
- `505 HTTP Version Not Supported` error.
737
+ all of the > following versions: `2.0`, `1.1`, and `1.0`. If Fastify receives a
738
+ different HTTP version in the request it will return a `505 HTTP Version Not
739
+ Supported` error.
665
740
 
666
741
  | | 2.0 | 1.1 | 1.0 | skip |
667
742
  |:------------------------:|:---:|:---:|:---:|:----:|
@@ -673,4 +748,4 @@ a different HTTP version in the request it will return a
673
748
  | serverFactory | | | | ✓ |
674
749
 
675
750
  Note: The internal HTTP version check will be removed in the future when Node
676
- implements [this feature](https://github.com/nodejs/node/issues/43115).
751
+ implements [this feature](https://github.com/nodejs/node/issues/43115).