fastify 3.27.4 → 4.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/.taprc +3 -0
  2. package/README.md +7 -7
  3. package/build/build-error-serializer.js +27 -0
  4. package/build/build-validation.js +47 -35
  5. package/docs/Guides/Database.md +320 -0
  6. package/docs/Guides/Ecosystem.md +9 -0
  7. package/docs/Guides/Getting-Started.md +7 -7
  8. package/docs/Guides/Plugins-Guide.md +1 -1
  9. package/docs/Guides/Serverless.md +3 -3
  10. package/docs/Guides/Testing.md +2 -2
  11. package/docs/Migration-Guide-V4.md +12 -0
  12. package/docs/Reference/ContentTypeParser.md +4 -0
  13. package/docs/Reference/Decorators.md +2 -2
  14. package/docs/Reference/Encapsulation.md +2 -2
  15. package/docs/Reference/Errors.md +51 -6
  16. package/docs/Reference/HTTP2.md +3 -3
  17. package/docs/Reference/Hooks.md +4 -7
  18. package/docs/Reference/LTS.md +5 -4
  19. package/docs/Reference/Plugins.md +3 -3
  20. package/docs/Reference/Reply.md +73 -22
  21. package/docs/Reference/Request.md +1 -3
  22. package/docs/Reference/Routes.md +22 -15
  23. package/docs/Reference/Server.md +69 -119
  24. package/docs/Reference/TypeScript.md +20 -22
  25. package/docs/Reference/Validation-and-Serialization.md +30 -55
  26. package/docs/Type-Providers.md +257 -0
  27. package/examples/asyncawait.js +1 -1
  28. package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
  29. package/examples/benchmark/hooks-benchmark.js +1 -1
  30. package/examples/benchmark/simple.js +1 -1
  31. package/examples/hooks.js +2 -2
  32. package/examples/http2.js +1 -1
  33. package/examples/https.js +1 -1
  34. package/examples/parser.js +13 -3
  35. package/examples/route-prefix.js +1 -1
  36. package/examples/shared-schema.js +1 -1
  37. package/examples/simple-stream.js +18 -0
  38. package/examples/simple.js +1 -1
  39. package/examples/simple.mjs +1 -1
  40. package/examples/typescript-server.ts +1 -1
  41. package/examples/use-plugin.js +1 -1
  42. package/fastify.d.ts +34 -22
  43. package/fastify.js +40 -36
  44. package/lib/configValidator.js +902 -1023
  45. package/lib/contentTypeParser.js +6 -16
  46. package/lib/context.js +36 -10
  47. package/lib/decorate.js +3 -1
  48. package/lib/error-handler.js +158 -0
  49. package/lib/error-serializer.js +257 -0
  50. package/lib/errors.js +51 -9
  51. package/lib/fourOhFour.js +31 -20
  52. package/lib/handleRequest.js +10 -13
  53. package/lib/hooks.js +14 -9
  54. package/lib/pluginOverride.js +0 -3
  55. package/lib/pluginUtils.js +3 -2
  56. package/lib/reply.js +121 -175
  57. package/lib/request.js +13 -10
  58. package/lib/route.js +131 -138
  59. package/lib/schema-controller.js +2 -2
  60. package/lib/schemas.js +27 -1
  61. package/lib/server.js +242 -116
  62. package/lib/symbols.js +5 -3
  63. package/lib/validation.js +11 -9
  64. package/lib/warnings.js +4 -12
  65. package/lib/wrapThenable.js +4 -11
  66. package/package.json +37 -39
  67. package/test/404s.test.js +258 -125
  68. package/test/500s.test.js +3 -3
  69. package/test/als.test.js +1 -1
  70. package/test/async-await.test.js +20 -76
  71. package/test/bodyLimit.test.js +1 -1
  72. package/test/build-certificate.js +6 -7
  73. package/test/case-insensitive.test.js +4 -4
  74. package/test/close-pipelining.test.js +2 -2
  75. package/test/close.test.js +11 -11
  76. package/test/content-parser.test.js +32 -0
  77. package/test/context-config.test.js +52 -0
  78. package/test/custom-http-server.test.js +14 -7
  79. package/test/custom-parser-async.test.js +1 -66
  80. package/test/custom-parser.test.js +92 -159
  81. package/test/custom-querystring-parser.test.js +3 -3
  82. package/test/decorator.test.js +11 -13
  83. package/test/delete.test.js +6 -6
  84. package/test/encapsulated-error-handler.test.js +50 -0
  85. package/test/esm/index.test.js +0 -14
  86. package/test/fastify-instance.test.js +4 -4
  87. package/test/fluent-schema.test.js +4 -4
  88. package/test/genReqId.test.js +1 -1
  89. package/test/get.test.js +4 -4
  90. package/test/handler-context.test.js +2 -2
  91. package/test/head.test.js +1 -1
  92. package/test/helper.js +19 -4
  93. package/test/hooks-async.test.js +15 -48
  94. package/test/hooks.on-ready.test.js +10 -5
  95. package/test/hooks.test.js +78 -119
  96. package/test/http2/closing.test.js +10 -16
  97. package/test/http2/constraint.test.js +1 -1
  98. package/test/http2/head.test.js +1 -1
  99. package/test/http2/plain.test.js +1 -1
  100. package/test/http2/secure-with-fallback.test.js +1 -1
  101. package/test/http2/secure.test.js +1 -1
  102. package/test/http2/unknown-http-method.test.js +4 -10
  103. package/test/https/custom-https-server.test.js +12 -6
  104. package/test/https/https.test.js +1 -1
  105. package/test/input-validation.js +3 -3
  106. package/test/internals/handleRequest.test.js +6 -43
  107. package/test/internals/initialConfig.test.js +41 -12
  108. package/test/internals/logger.test.js +2 -2
  109. package/test/internals/reply.test.js +317 -48
  110. package/test/internals/request.test.js +13 -7
  111. package/test/internals/server.test.js +88 -0
  112. package/test/listen.deprecated.test.js +202 -0
  113. package/test/listen.test.js +140 -145
  114. package/test/logger.test.js +82 -42
  115. package/test/maxRequestsPerSocket.test.js +8 -6
  116. package/test/middleware.test.js +2 -25
  117. package/test/nullable-validation.test.js +53 -16
  118. package/test/output-validation.test.js +1 -1
  119. package/test/plugin.test.js +47 -21
  120. package/test/pretty-print.test.js +22 -10
  121. package/test/promises.test.js +1 -1
  122. package/test/proto-poisoning.test.js +6 -6
  123. package/test/register.test.js +3 -3
  124. package/test/reply-error.test.js +126 -15
  125. package/test/reply-trailers.test.js +270 -0
  126. package/test/request-error.test.js +3 -6
  127. package/test/route-hooks.test.js +18 -18
  128. package/test/route-prefix.test.js +2 -1
  129. package/test/route.test.js +206 -22
  130. package/test/router-options.test.js +2 -2
  131. package/test/schema-examples.test.js +11 -5
  132. package/test/schema-feature.test.js +25 -20
  133. package/test/schema-serialization.test.js +9 -9
  134. package/test/schema-special-usage.test.js +5 -153
  135. package/test/schema-validation.test.js +9 -9
  136. package/test/skip-reply-send.test.js +2 -2
  137. package/test/stream.test.js +82 -23
  138. package/test/throw.test.js +8 -5
  139. package/test/trust-proxy.test.js +6 -6
  140. package/test/type-provider.test.js +20 -0
  141. package/test/types/fastify.test-d.ts +10 -18
  142. package/test/types/hooks.test-d.ts +61 -5
  143. package/test/types/import.js +2 -0
  144. package/test/types/import.ts +1 -0
  145. package/test/types/instance.test-d.ts +68 -17
  146. package/test/types/logger.test-d.ts +44 -15
  147. package/test/types/reply.test-d.ts +2 -1
  148. package/test/types/request.test-d.ts +71 -1
  149. package/test/types/route.test-d.ts +8 -2
  150. package/test/types/schema.test-d.ts +2 -39
  151. package/test/types/type-provider.test-d.ts +424 -0
  152. package/test/url-rewriting.test.js +3 -3
  153. package/test/validation-error-handling.test.js +8 -8
  154. package/test/versioned-routes.test.js +30 -18
  155. package/test/wrapThenable.test.js +7 -6
  156. package/types/content-type-parser.d.ts +17 -8
  157. package/types/hooks.d.ts +182 -85
  158. package/types/instance.d.ts +286 -118
  159. package/types/logger.d.ts +18 -104
  160. package/types/plugin.d.ts +10 -4
  161. package/types/reply.d.ts +18 -12
  162. package/types/request.d.ts +13 -8
  163. package/types/route.d.ts +62 -34
  164. package/types/schema.d.ts +1 -1
  165. package/types/type-provider.d.ts +99 -0
  166. package/types/utils.d.ts +1 -1
  167. package/lib/schema-compilers.js +0 -12
  168. package/test/emit-warning.test.js +0 -166
@@ -47,6 +47,7 @@ describes the properties available in that options object.
47
47
  - [after](#after)
48
48
  - [ready](#ready)
49
49
  - [listen](#listen)
50
+ - [addresses](#addresses)
50
51
  - [getDefaultRoute](#getdefaultroute)
51
52
  - [setDefaultRoute](#setdefaultroute)
52
53
  - [routing](#routing)
@@ -126,7 +127,7 @@ property](https://nodejs.org/api/http.html#http_server_keepalivetimeout) to
126
127
  understand the effect of this option. This option only applies when HTTP/1 is in
127
128
  use. Also, when `serverFactory` option is specified, this option is ignored.
128
129
 
129
- + Default: `5000` (5 seconds)
130
+ + Default: `72000` (72 seconds)
130
131
 
131
132
  ### `forceCloseConnections`
132
133
  <a id="forcecloseconnections"></a>
@@ -352,7 +353,7 @@ fastify.get('/', (req, reply) => {
352
353
  reply.send({ hello: 'world' })
353
354
  })
354
355
 
355
- fastify.listen(3000)
356
+ fastify.listen({ port: 3000 })
356
357
  ```
357
358
 
358
359
  Internally Fastify uses the API of Node core HTTP server, so if you are using a
@@ -513,7 +514,8 @@ derive <code>request.hostname</code> and <code>request.protocol</code>**
513
514
 
514
515
  The maximum amount of time in *milliseconds* in which a plugin can load. If not,
515
516
  [`ready`](#ready) will complete with an `Error` with code
516
- `'ERR_AVVIO_PLUGIN_TIMEOUT'`.
517
+ `'ERR_AVVIO_PLUGIN_TIMEOUT'`. When set to `0`, disables this check. This controls
518
+ [avvio](https://www.npmjs.com/package/avvio) 's `timeout` parameter.
517
519
 
518
520
  + Default: `10000`
519
521
 
@@ -553,7 +555,7 @@ Automatically creates a sibling `HEAD` route for each `GET` route defined. If
553
555
  you want a custom `HEAD` handler without disabling this option, make sure to
554
556
  define it before the `GET` route.
555
557
 
556
- + Default: `false`
558
+ + Default: `true`
557
559
 
558
560
  ### `constraints`
559
561
  <a id="constraints"></a>
@@ -599,28 +601,14 @@ the incoming request as usual.
599
601
  ### `ajv`
600
602
  <a id="factory-ajv"></a>
601
603
 
602
- Configure the Ajv v6 instance used by Fastify without providing a custom one.
603
-
604
- + Default:
605
-
606
- ```js
607
- {
608
- customOptions: {
609
- removeAdditional: true,
610
- useDefaults: true,
611
- coerceTypes: true,
612
- allErrors: false,
613
- nullable: true
614
- },
615
- plugins: []
616
- }
617
- ```
604
+ Configure the Ajv v8 instance used by Fastify without providing a custom one.
605
+ The default configuration is explained in the [#schema-validator](Validation-and-Serialization.md#schema-validator) section.
618
606
 
619
607
  ```js
620
608
  const fastify = require('fastify')({
621
609
  ajv: {
622
610
  customOptions: {
623
- nullable: false // Refer to [ajv options](https://github.com/ajv-validator/ajv/tree/v6#options)
611
+ removeAdditional: 'all' // Refer to [ajv options](https://ajv.js.org/#options)
624
612
  },
625
613
  plugins: [
626
614
  require('ajv-merge-patch'),
@@ -653,7 +641,7 @@ const fastify = require('fastify')({
653
641
  Set a default
654
642
  [timeout](https://nodejs.org/api/http2.html#http2_http2session_settimeout_msecs_callback)
655
643
  to every incoming HTTP/2 session. The session will be closed on the timeout.
656
- Default: `5000` ms.
644
+ Default: `72000` ms.
657
645
 
658
646
  Note that this is needed to offer the graceful "close" experience when using
659
647
  HTTP/2. The low default has been chosen to mitigate denial of service attacks.
@@ -833,41 +821,40 @@ fastify.ready().then(() => {
833
821
  #### listen
834
822
  <a id="listen"></a>
835
823
 
836
- Starts the server on the given port after all the plugins are loaded, internally
837
- waits for the `.ready()` event. The callback is the same as the Node core. By
838
- default, the server will listen on the address resolved by `localhost` when no
839
- specific address is provided (`127.0.0.1` or `::1` depending on the operating
840
- system). If listening on any available interface is desired, then specifying
841
- `0.0.0.0` for the address will listen on all IPv4 addresses. Using `::` for the
842
- address will listen on all IPv6 addresses and, depending on OS, may also listen
843
- on all IPv4 addresses. Be careful when deciding to listen on all interfaces; it
844
- comes with inherent [security
824
+ Starts the server and internally waits for the `.ready()` event. The
825
+ signature is `.listen([options][, callback])`. Both the `options` object and the
826
+ `callback` parameters follow the [Node.js
827
+ core][https://nodejs.org/api/net.html#serverlistenoptions-callback] parameter
828
+ definitions.
829
+
830
+ By default, the server will listen on the address(es) resolved by `localhost` when no
831
+ specific host is provided. If listening on any available interface is desired,
832
+ then specifying `0.0.0.0` for the address will listen on all IPv4 addresses.
833
+ The following table details the possible values for `host` when targeting
834
+ `localhost`, and what the result of those values for `host` will be.
835
+
836
+ Host | IPv4 | IPv6
837
+ --------------|------|-------
838
+ `::` | ✅<sup>*</sup> | ✅
839
+ `::` + [`ipv6Only`](https://nodejs.org/api/net.html#serverlistenoptions-callback) | 🚫 | ✅
840
+ `0.0.0.0` | ✅ | 🚫
841
+ `localhost` | ✅ | ✅
842
+ `127.0.0.1` | ✅ | 🚫
843
+ `::1` | 🚫 | ✅
844
+
845
+ <sup>*</sup> Using `::` for the address will listen on all IPv6 addresses and,
846
+ depending on OS, may also listen on [all IPv4
847
+ addresses](https://nodejs.org/api/net.html#serverlistenport-host-backlog-callback).
848
+
849
+ Be careful when deciding to listen on all interfaces; it comes with inherent
850
+ [security
845
851
  risks](https://web.archive.org/web/20170831174611/https://snyk.io/blog/mongodb-hack-and-secure-defaults/).
846
852
 
847
- ```js
848
- fastify.listen(3000, (err, address) => {
849
- if (err) {
850
- fastify.log.error(err)
851
- process.exit(1)
852
- }
853
- })
854
- ```
855
-
856
- Specifying an address is also supported:
857
-
858
- ```js
859
- fastify.listen(3000, '127.0.0.1', (err, address) => {
860
- if (err) {
861
- fastify.log.error(err)
862
- process.exit(1)
863
- }
864
- })
865
- ```
866
-
867
- Specifying a backlog queue size is also supported:
853
+ The default is to listen on `port: 0` (which picks the first available open
854
+ port) and `host: 'localhost'`:
868
855
 
869
856
  ```js
870
- fastify.listen(3000, '127.0.0.1', 511, (err, address) => {
857
+ fastify.listen((err, address) => {
871
858
  if (err) {
872
859
  fastify.log.error(err)
873
860
  process.exit(1)
@@ -875,12 +862,10 @@ fastify.listen(3000, '127.0.0.1', 511, (err, address) => {
875
862
  })
876
863
  ```
877
864
 
878
- Specifying options is also supported; the object is same as
879
- [options](https://nodejs.org/api/net.html#net_server_listen_options_callback) in
880
- the Node.js server listen:
865
+ Specifying an address is also supported:
881
866
 
882
867
  ```js
883
- fastify.listen({ port: 3000, host: '127.0.0.1', backlog: 511 }, (err) => {
868
+ fastify.listen({ port: 3000, host: '127.0.0.1' }, (err, address) => {
884
869
  if (err) {
885
870
  fastify.log.error(err)
886
871
  process.exit(1)
@@ -891,29 +876,7 @@ fastify.listen({ port: 3000, host: '127.0.0.1', backlog: 511 }, (err) => {
891
876
  If no callback is provided a Promise is returned:
892
877
 
893
878
  ```js
894
- fastify.listen(3000)
895
- .then((address) => console.log(`server listening on ${address}`))
896
- .catch(err => {
897
- console.log('Error starting server:', err)
898
- process.exit(1)
899
- })
900
- ```
901
-
902
- Specifying an address without a callback is also supported:
903
-
904
- ```js
905
- fastify.listen(3000, '127.0.0.1')
906
- .then((address) => console.log(`server listening on ${address}`))
907
- .catch(err => {
908
- console.log('Error starting server:', err)
909
- process.exit(1)
910
- })
911
- ```
912
-
913
- Specifying options without a callback is also supported:
914
-
915
- ```js
916
- fastify.listen({ port: 3000, host: '127.0.0.1', backlog: 511 })
879
+ fastify.listen({ port: 3000 })
917
880
  .then((address) => console.log(`server listening on ${address}`))
918
881
  .catch(err => {
919
882
  console.log('Error starting server:', err)
@@ -926,7 +889,7 @@ to listen on `0.0.0.0` because they do not default to exposing mapped ports to
926
889
  `localhost`:
927
890
 
928
891
  ```js
929
- fastify.listen(3000, '0.0.0.0', (err, address) => {
892
+ fastify.listen({ port: 3000, host: '0.0.0.0' }, (err, address) => {
930
893
  if (err) {
931
894
  fastify.log.error(err)
932
895
  process.exit(1)
@@ -935,7 +898,7 @@ fastify.listen(3000, '0.0.0.0', (err, address) => {
935
898
  ```
936
899
 
937
900
  If the `port` is omitted (or is set to zero), a random available port is
938
- automatically chosen (later available via `fastify.server.address().port`).
901
+ automatically chosen (available via `fastify.server.address().port`).
939
902
 
940
903
  The default options of listen are:
941
904
 
@@ -950,6 +913,24 @@ fastify.listen({
950
913
  }, (err) => {})
951
914
  ```
952
915
 
916
+ #### addresses
917
+ <a id="addresses"></a>
918
+
919
+ This method returns an array of addresses that the server is listening on.
920
+ If you call it before `listen()` is called or after the `close()` function,
921
+ it will return an empty array.
922
+
923
+ ```js
924
+ await fastify.listen({ port: 8080 })
925
+ const addresses = fastify.addresses()
926
+ // [
927
+ // { port: 8080, family: 'IPv6', address: '::1' },
928
+ // { port: 8080, family: 'IPv4', address: '127.0.0.1' }
929
+ // ]
930
+ ```
931
+
932
+ Note that the array contains the `fastify.server.address()` too.
933
+
953
934
  #### getDefaultRoute
954
935
  <a id="getDefaultRoute"></a>
955
936
 
@@ -1188,8 +1169,10 @@ unknown to Fastify. See [issue
1188
1169
  #2446](https://github.com/fastify/fastify/issues/2446) for an example of what
1189
1170
  this property helps to resolve.
1190
1171
 
1191
- Another use case is to tweak all the schemas processing. Doing so it is possible
1192
- to use Ajv v8, instead of the default v6! We will see an example of this later.
1172
+ Another use case is to tweak all the schemas processing.
1173
+ Doing so it is possible to use Ajv v8 JTD or Standalone feature. To use such
1174
+ as JTD or the Standalone mode, refers to the
1175
+ [`@fastify/ajv-compiler` documentation](https://github.com/fastify/ajv-compiler#usage).
1193
1176
 
1194
1177
  ```js
1195
1178
  const fastify = Fastify({
@@ -1264,39 +1247,6 @@ const fastify = Fastify({
1264
1247
  });
1265
1248
  ```
1266
1249
 
1267
- ##### Ajv 8 as default schema validator
1268
-
1269
- Ajv 8 is the evolution of Ajv 6, and it has a lot of improvements and new
1270
- features. To use the new Ajv 8 features such as JTD or the Standalone mode,
1271
- refer to the [`@fastify/ajv-compiler`
1272
- documentation](https://github.com/fastify/ajv-compiler#usage).
1273
-
1274
- To use Ajv 8 as default schema validator, you can use the following code:
1275
-
1276
- ```js
1277
- const AjvCompiler = require('@fastify/ajv-compiler') // It must be the v2.x.x version
1278
-
1279
- // Note that the `format` schema's keyword is no longer supported on Ajv 8 by default.
1280
- // So you need to add it manually.
1281
- const ajvFormats = require('ajv-formats')
1282
-
1283
- const app = fastify({
1284
- ajv: {
1285
- customOptions: {
1286
- validateFormats: true
1287
- },
1288
- plugins: [ajvFormats]
1289
- },
1290
- schemaController: {
1291
- compilersFactory: {
1292
- buildValidator: AjvCompiler()
1293
- }
1294
- }
1295
- })
1296
-
1297
- // Done! You can now use Ajv 8 options and keywords in your schemas!
1298
- ```
1299
-
1300
1250
  #### setNotFoundHandler
1301
1251
  <a id="set-not-found-handler"></a>
1302
1252
 
@@ -1485,7 +1435,7 @@ fastify.addContentTypeParser('text/json', { asString: true }, fastify.getDefault
1485
1435
  #### hasContentTypeParser
1486
1436
  <a id="hasContentTypeParser"></a>
1487
1437
 
1488
- `fastify.hasContentTypeParser(contentType)` is used to check whether there is a content type parser in the current
1438
+ `fastify.hasContentTypeParser(contentType)` is used to check whether there is a content type parser in the current
1489
1439
  context for the specified content type.
1490
1440
 
1491
1441
  ```js
@@ -1629,7 +1579,7 @@ fastify.register(async (instance, opts) => {
1629
1579
  })
1630
1580
 
1631
1581
  // Start listening.
1632
- fastify.listen(3000, (err) => {
1582
+ fastify.listen({ port: 3000 }, (err) => {
1633
1583
  if (err) {
1634
1584
  fastify.log.error(err)
1635
1585
  process.exit(1)
@@ -72,7 +72,7 @@ in a blank http Fastify server.
72
72
  return 'pong\n'
73
73
  })
74
74
 
75
- server.listen(8080, (err, address) => {
75
+ server.listen({ port: 8080 }, (err, address) => {
76
76
  if (err) {
77
77
  console.error(err)
78
78
  process.exit(1)
@@ -360,7 +360,7 @@ into TypeScript interfaces!
360
360
  }
361
361
  })
362
362
 
363
- server.listen(8080, (err, address) => {
363
+ server.listen({ port: 8080 }, (err, address) => {
364
364
  if (err) {
365
365
  console.error(err)
366
366
  process.exit(0)
@@ -399,7 +399,7 @@ const todo = {
399
399
  done: { type: 'boolean' },
400
400
  },
401
401
  required: ['name'],
402
- } as const;
402
+ } as const; // don't forget to use const !
403
403
  ```
404
404
 
405
405
  With the provided type `FromSchema` you can build a type from your schema and
@@ -487,6 +487,7 @@ Fastify Plugin in a TypeScript Project.
487
487
  import fp from 'fastify-plugin'
488
488
 
489
489
  // using declaration merging, add your plugin props to the appropriate fastify interfaces
490
+ // if prop type is defined here, the value will be typechecked when you call decorate{,Request,Reply}
490
491
  declare module 'fastify' {
491
492
  interface FastifyRequest {
492
493
  myPluginProp: string
@@ -680,21 +681,21 @@ There are a couple supported import methods with the Fastify type system.
680
681
  import fastify from 'fastify'
681
682
 
682
683
  const f = fastify()
683
- f.listen(8080, () => { console.log('running') })
684
+ f.listen({ port: 8080 }, () => { console.log('running') })
684
685
  ```
685
686
  - Gain access to types with destructuring:
686
687
  ```typescript
687
688
  import fastify, { FastifyInstance } from 'fastify'
688
689
 
689
690
  const f: FastifyInstance = fastify()
690
- f.listen(8080, () => { console.log('running') })
691
+ f.listen({ port: 8080 }, () => { console.log('running') })
691
692
  ```
692
693
  - Destructuring also works for the main API method:
693
694
  ```typescript
694
695
  import { fastify, FastifyInstance } from 'fastify'
695
696
 
696
697
  const f: FastifyInstance = fastify()
697
- f.listen(8080, () => { console.log('running') })
698
+ f.listen({ port: 8080 }, () => { console.log('running') })
698
699
  ```
699
700
  2. `import * as Fastify from 'fastify'`
700
701
  - Types are resolved and accessible using dot notation
@@ -705,7 +706,7 @@ There are a couple supported import methods with the Fastify type system.
705
706
  import * as Fastify from 'fastify'
706
707
 
707
708
  const f: Fastify.FastifyInstance = Fastify.fastify()
708
- f.listen(8080, () => { console.log('running') })
709
+ f.listen({ port: 8080 }, () => { console.log('running') })
709
710
  ```
710
711
  3. `const fastify = require('fastify')`
711
712
  - This syntax is valid and will import fastify as expected; however, types
@@ -715,14 +716,14 @@ There are a couple supported import methods with the Fastify type system.
715
716
  const fastify = require('fastify')
716
717
 
717
718
  const f = fastify()
718
- f.listen(8080, () => { console.log('running') })
719
+ f.listen({ port: 8080 }, () => { console.log('running') })
719
720
  ```
720
721
  - Destructuring is supported and will resolve types properly
721
722
  ```typescript
722
723
  const { fastify } = require('fastify')
723
724
 
724
725
  const f = fastify()
725
- f.listen(8080, () => { console.log('running') })
726
+ f.listen({ port: 8080 }, () => { console.log('running') })
726
727
  ```
727
728
 
728
729
  #### Generics
@@ -824,7 +825,7 @@ a more detailed http server walkthrough.
824
825
  return { hello: 'world' }
825
826
  })
826
827
 
827
- server.listen(8080, (err, address) => {
828
+ server.listen({ port: 8080 }, (err, address) => {
828
829
  if (err) {
829
830
  console.error(err)
830
831
  process.exit(0)
@@ -877,26 +878,23 @@ server.get('/', async (request, reply) => {
877
878
 
878
879
  ###### Example 5: Specifying logger types
879
880
 
880
- Fastify uses [Pino](https://getpino.io/#/) logging library under the hood. Some
881
- of it's properties can be configured via `logger` field when constructing
882
- Fastify's instance. If properties you need aren't exposed, it's also possible to
883
- pass a preconfigured external instance of Pino (or any other compatible logger)
884
- to Fastify via the same field. This allows creating custom serializers as well,
885
- see the [Logging](./Logging.md) documentation for more info.
886
-
887
- To use an external instance of Pino, add `@types/pino` to devDependencies and
888
- pass the instance to `logger` field:
881
+ Fastify uses [Pino](https://getpino.io/#/) logging library under the hood. Since
882
+ `pino@7`, all of it's properties can be configured via `logger` field when
883
+ constructing Fastify's instance. If properties you need aren't exposed, please
884
+ open an Issue to [`Pino`](https://github.com/pinojs/pino/issues) or pass a
885
+ preconfigured external instance of Pino (or any other compatible logger) as
886
+ temporary fix to Fastify via the same field. This allows creating custom
887
+ serializers as well, see the [Logging](Logging.md) documentation for more info.
889
888
 
890
889
  ```typescript
891
890
  import fastify from 'fastify'
892
- import pino from 'pino'
893
891
 
894
892
  const server = fastify({
895
- logger: pino({
893
+ logger: {
896
894
  level: 'info',
897
895
  redact: ['x-userinfo'],
898
896
  messageKey: 'message'
899
- })
897
+ }
900
898
  })
901
899
 
902
900
  server.get('/', async (request, reply) => {
@@ -4,11 +4,13 @@
4
4
  Fastify uses a schema-based approach, and even if it is not mandatory we
5
5
  recommend using [JSON Schema](https://json-schema.org/) to validate your routes
6
6
  and serialize your outputs. Internally, Fastify compiles the schema into a
7
- highly performant function.
7
+ highly performant function.
8
8
 
9
9
  Validation will only be attempted if the content type is `application-json`,
10
10
  as described in the documentation for the [content type parser](./ContentTypeParser.md).
11
11
 
12
+ All the examples in this section are using the [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7) specification.
13
+
12
14
  > ## ⚠ Security Notice
13
15
  > Treat the schema definition as application code. Validation and serialization
14
16
  > features dynamically evaluate code with `new Function()`, which is not safe to
@@ -26,8 +28,7 @@ as described in the documentation for the [content type parser](./ContentTypePar
26
28
  ### Core concepts
27
29
  The validation and the serialization tasks are processed by two different, and
28
30
  customizable, actors:
29
- - [Ajv v6](https://www.npmjs.com/package/ajv/v/6.12.6) for the validation of a
30
- request
31
+ - [Ajv v8](https://www.npmjs.com/package/ajv) for the validation of a request
31
32
  - [fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify) for
32
33
  the serialization of a response's body
33
34
 
@@ -146,10 +147,11 @@ fastify.register((instance, opts, done) => {
146
147
 
147
148
 
148
149
  ### Validation
149
- The route validation internally relies upon [Ajv
150
- v6](https://www.npmjs.com/package/ajv/v/6.12.6) which is a high-performance JSON
151
- Schema validator. Validating the input is very easy: just add the fields that
152
- you need inside the route schema, and you are done!
150
+ The route validation internally relies upon
151
+ [Ajv v8](https://www.npmjs.com/package/ajv) which is a high-performance
152
+ JSON Schema validator.
153
+ Validating the input is very easy: just add the fields that you need
154
+ inside the route schema, and you are done!
153
155
 
154
156
  The supported validations are:
155
157
  - `body`: validates the body of the request if it is a POST, PUT, or PATCH
@@ -232,15 +234,13 @@ const schema = {
232
234
  fastify.post('/the/url', { schema }, handler)
233
235
  ```
234
236
 
235
- *Note that Ajv will try to
236
- [coerce](https://github.com/epoberezkin/ajv#coercing-data-types) the values to
237
+ *Note that Ajv will try to [coerce](https://ajv.js.org/coercion.html) the values to
237
238
  the types specified in your schema `type` keywords, both to pass the validation
238
239
  and to use the correctly typed data afterwards.*
239
240
 
240
- The Ajv default configuration in Fastify doesn't support coercing array
241
- parameters in querystring. However, Fastify allows
242
- [`customOptions`](./Server.md#ajv) in Ajv instance. The `coerceTypes: 'array'`
243
- will coerce one parameter to a single element in array. Example:
241
+ The Ajv default configuration in Fastify supports coercing array
242
+ parameters in `querystring`.
243
+ Example:
244
244
 
245
245
  ```js
246
246
  const opts = {
@@ -258,37 +258,14 @@ const opts = {
258
258
  }
259
259
 
260
260
  fastify.get('/', opts, (request, reply) => {
261
- reply.send({ params: request.query })
261
+ reply.send({ params: request.query }) // echo the querystring
262
262
  })
263
263
 
264
- fastify.listen(3000, (err) => {
264
+ fastify.listen({ port: 3000 }, (err) => {
265
265
  if (err) throw err
266
266
  })
267
267
  ```
268
268
 
269
- Using Fastify defaults the following request will result in `400` status code:
270
-
271
- ```sh
272
- curl -X GET "http://localhost:3000/?ids=1
273
-
274
- {"statusCode":400,"error":"Bad Request","message":"querystring/hello should be array"}
275
- ```
276
-
277
- Using `coerceTypes` as 'array' will fix it:
278
-
279
- ```js
280
- const ajv = new Ajv({
281
- removeAdditional: true,
282
- useDefaults: true,
283
- coerceTypes: 'array', // This line
284
- allErrors: true
285
- })
286
-
287
- fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
288
- return ajv.compile(schema)
289
- })
290
- ```
291
-
292
269
  ```sh
293
270
  curl -X GET "http://localhost:3000/?ids=1
294
271
 
@@ -342,8 +319,8 @@ For further information see [here](https://ajv.js.org/coercion.html)
342
319
  #### Ajv Plugins
343
320
  <a id="ajv-plugins"></a>
344
321
 
345
- You can provide a list of plugins you want to use with the default `ajv`
346
- instance. Note that the plugin must be **compatible with Ajv v6**.
322
+ You can provide a list of plugins you want to use with the default `ajv` instance.
323
+ Note that the plugin must be **compatible with the Ajv version shipped within Fastify**.
347
324
 
348
325
  > Refer to [`ajv options`](./Server.md#ajv) to check plugins format
349
326
 
@@ -412,16 +389,16 @@ body, URL parameters, headers, and query string. The default
412
389
  [ajv](https://ajv.js.org/) validation interface. Fastify uses it internally to
413
390
  speed the validation up.
414
391
 
415
- Fastify's [baseline ajv
416
- configuration](https://github.com/epoberezkin/ajv#options-to-modify-validated-data)
417
- is:
392
+ Fastify's [baseline ajv configuration](https://github.com/fastify/ajv-compiler#ajv-configuration) is:
418
393
 
419
394
  ```js
420
395
  {
421
- removeAdditional: true, // remove additional properties
422
- useDefaults: true, // replace missing properties and items with the values from corresponding default keyword
423
396
  coerceTypes: true, // change data type of data to match type keyword
424
- nullable: true // support keyword "nullable" from Open API 3 specification.
397
+ useDefaults: true, // replace missing properties and items with the values from corresponding default keyword
398
+ removeAdditional: true, // remove additional properties
399
+ // Explicitly set allErrors to `false`.
400
+ // When set to `true`, a DoS attack is possible.
401
+ allErrors: false
425
402
  }
426
403
  ```
427
404
 
@@ -435,11 +412,9 @@ your own instance and override the existing one like:
435
412
  const fastify = require('fastify')()
436
413
  const Ajv = require('ajv')
437
414
  const ajv = new Ajv({
438
- // the fastify defaults (if needed)
439
- removeAdditional: true,
415
+ removeAdditional: 'all',
440
416
  useDefaults: true,
441
- coerceTypes: true,
442
- nullable: true,
417
+ coerceTypes: 'array',
443
418
  // any other options
444
419
  // ...
445
420
  })
@@ -460,7 +435,7 @@ almost any Javascript validation library ([joi](https://github.com/hapijs/joi/),
460
435
  [yup](https://github.com/jquense/yup/), ...) or a custom one:
461
436
 
462
437
  ```js
463
- const Joi = require('@hapi/joi')
438
+ const Joi = require('joi')
464
439
 
465
440
  fastify.post('/the/url', {
466
441
  schema: {
@@ -512,8 +487,8 @@ fastify.post('/the/url', {
512
487
 
513
488
  Fastify's validation error messages are tightly coupled to the default
514
489
  validation engine: errors returned from `ajv` are eventually run through the
515
- `schemaErrorsText` function which is responsible for building human-friendly
516
- error messages. However, the `schemaErrorsText` function is written with `ajv`
490
+ `schemaErrorFormatter` function which is responsible for building human-friendly
491
+ error messages. However, the `schemaErrorFormatter` function is written with `ajv`
517
492
  in mind : as a result, you may run into odd or incomplete error messages when
518
493
  using other validation libraries.
519
494
 
@@ -529,9 +504,9 @@ To circumvent this issue, you have 2 main options :
529
504
  To help you in writing a custom `errorHandler`, Fastify adds 2 properties to all
530
505
  validation errors:
531
506
 
532
- * validation: the content of the `error` property of the object returned by the
507
+ * `validation`: the content of the `error` property of the object returned by the
533
508
  validation function (returned by your custom `schemaCompiler`)
534
- * validationContext: the 'context' (body, params, query, headers) where the
509
+ * `validationContext`: the 'context' (body, params, query, headers) where the
535
510
  validation error occurred
536
511
 
537
512
  A very contrived example of such a custom `errorHandler` handling validation