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.
- package/.taprc +3 -0
- package/README.md +7 -7
- package/build/build-error-serializer.js +27 -0
- package/build/build-validation.js +47 -35
- package/docs/Guides/Database.md +320 -0
- package/docs/Guides/Ecosystem.md +9 -0
- package/docs/Guides/Getting-Started.md +7 -7
- package/docs/Guides/Plugins-Guide.md +1 -1
- package/docs/Guides/Serverless.md +3 -3
- package/docs/Guides/Testing.md +2 -2
- package/docs/Migration-Guide-V4.md +12 -0
- package/docs/Reference/ContentTypeParser.md +4 -0
- package/docs/Reference/Decorators.md +2 -2
- package/docs/Reference/Encapsulation.md +2 -2
- package/docs/Reference/Errors.md +51 -6
- package/docs/Reference/HTTP2.md +3 -3
- package/docs/Reference/Hooks.md +4 -7
- package/docs/Reference/LTS.md +5 -4
- package/docs/Reference/Plugins.md +3 -3
- package/docs/Reference/Reply.md +73 -22
- package/docs/Reference/Request.md +1 -3
- package/docs/Reference/Routes.md +22 -15
- package/docs/Reference/Server.md +69 -119
- package/docs/Reference/TypeScript.md +20 -22
- package/docs/Reference/Validation-and-Serialization.md +30 -55
- package/docs/Type-Providers.md +257 -0
- package/examples/asyncawait.js +1 -1
- package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
- package/examples/benchmark/hooks-benchmark.js +1 -1
- package/examples/benchmark/simple.js +1 -1
- package/examples/hooks.js +2 -2
- package/examples/http2.js +1 -1
- package/examples/https.js +1 -1
- package/examples/parser.js +13 -3
- package/examples/route-prefix.js +1 -1
- package/examples/shared-schema.js +1 -1
- package/examples/simple-stream.js +18 -0
- package/examples/simple.js +1 -1
- package/examples/simple.mjs +1 -1
- package/examples/typescript-server.ts +1 -1
- package/examples/use-plugin.js +1 -1
- package/fastify.d.ts +34 -22
- package/fastify.js +40 -36
- package/lib/configValidator.js +902 -1023
- package/lib/contentTypeParser.js +6 -16
- package/lib/context.js +36 -10
- package/lib/decorate.js +3 -1
- package/lib/error-handler.js +158 -0
- package/lib/error-serializer.js +257 -0
- package/lib/errors.js +51 -9
- package/lib/fourOhFour.js +31 -20
- package/lib/handleRequest.js +10 -13
- package/lib/hooks.js +14 -9
- package/lib/pluginOverride.js +0 -3
- package/lib/pluginUtils.js +3 -2
- package/lib/reply.js +121 -175
- package/lib/request.js +13 -10
- package/lib/route.js +131 -138
- package/lib/schema-controller.js +2 -2
- package/lib/schemas.js +27 -1
- package/lib/server.js +242 -116
- package/lib/symbols.js +5 -3
- package/lib/validation.js +11 -9
- package/lib/warnings.js +4 -12
- package/lib/wrapThenable.js +4 -11
- package/package.json +37 -39
- package/test/404s.test.js +258 -125
- package/test/500s.test.js +3 -3
- package/test/als.test.js +1 -1
- package/test/async-await.test.js +20 -76
- package/test/bodyLimit.test.js +1 -1
- package/test/build-certificate.js +6 -7
- package/test/case-insensitive.test.js +4 -4
- package/test/close-pipelining.test.js +2 -2
- package/test/close.test.js +11 -11
- package/test/content-parser.test.js +32 -0
- package/test/context-config.test.js +52 -0
- package/test/custom-http-server.test.js +14 -7
- package/test/custom-parser-async.test.js +1 -66
- package/test/custom-parser.test.js +92 -159
- package/test/custom-querystring-parser.test.js +3 -3
- package/test/decorator.test.js +11 -13
- package/test/delete.test.js +6 -6
- package/test/encapsulated-error-handler.test.js +50 -0
- package/test/esm/index.test.js +0 -14
- package/test/fastify-instance.test.js +4 -4
- package/test/fluent-schema.test.js +4 -4
- package/test/genReqId.test.js +1 -1
- package/test/get.test.js +4 -4
- package/test/handler-context.test.js +2 -2
- package/test/head.test.js +1 -1
- package/test/helper.js +19 -4
- package/test/hooks-async.test.js +15 -48
- package/test/hooks.on-ready.test.js +10 -5
- package/test/hooks.test.js +78 -119
- package/test/http2/closing.test.js +10 -16
- package/test/http2/constraint.test.js +1 -1
- package/test/http2/head.test.js +1 -1
- package/test/http2/plain.test.js +1 -1
- package/test/http2/secure-with-fallback.test.js +1 -1
- package/test/http2/secure.test.js +1 -1
- package/test/http2/unknown-http-method.test.js +4 -10
- package/test/https/custom-https-server.test.js +12 -6
- package/test/https/https.test.js +1 -1
- package/test/input-validation.js +3 -3
- package/test/internals/handleRequest.test.js +6 -43
- package/test/internals/initialConfig.test.js +41 -12
- package/test/internals/logger.test.js +2 -2
- package/test/internals/reply.test.js +317 -48
- package/test/internals/request.test.js +13 -7
- package/test/internals/server.test.js +88 -0
- package/test/listen.deprecated.test.js +202 -0
- package/test/listen.test.js +140 -145
- package/test/logger.test.js +82 -42
- package/test/maxRequestsPerSocket.test.js +8 -6
- package/test/middleware.test.js +2 -25
- package/test/nullable-validation.test.js +53 -16
- package/test/output-validation.test.js +1 -1
- package/test/plugin.test.js +47 -21
- package/test/pretty-print.test.js +22 -10
- package/test/promises.test.js +1 -1
- package/test/proto-poisoning.test.js +6 -6
- package/test/register.test.js +3 -3
- package/test/reply-error.test.js +126 -15
- package/test/reply-trailers.test.js +270 -0
- package/test/request-error.test.js +3 -6
- package/test/route-hooks.test.js +18 -18
- package/test/route-prefix.test.js +2 -1
- package/test/route.test.js +206 -22
- package/test/router-options.test.js +2 -2
- package/test/schema-examples.test.js +11 -5
- package/test/schema-feature.test.js +25 -20
- package/test/schema-serialization.test.js +9 -9
- package/test/schema-special-usage.test.js +5 -153
- package/test/schema-validation.test.js +9 -9
- package/test/skip-reply-send.test.js +2 -2
- package/test/stream.test.js +82 -23
- package/test/throw.test.js +8 -5
- package/test/trust-proxy.test.js +6 -6
- package/test/type-provider.test.js +20 -0
- package/test/types/fastify.test-d.ts +10 -18
- package/test/types/hooks.test-d.ts +61 -5
- package/test/types/import.js +2 -0
- package/test/types/import.ts +1 -0
- package/test/types/instance.test-d.ts +68 -17
- package/test/types/logger.test-d.ts +44 -15
- package/test/types/reply.test-d.ts +2 -1
- package/test/types/request.test-d.ts +71 -1
- package/test/types/route.test-d.ts +8 -2
- package/test/types/schema.test-d.ts +2 -39
- package/test/types/type-provider.test-d.ts +424 -0
- package/test/url-rewriting.test.js +3 -3
- package/test/validation-error-handling.test.js +8 -8
- package/test/versioned-routes.test.js +30 -18
- package/test/wrapThenable.test.js +7 -6
- package/types/content-type-parser.d.ts +17 -8
- package/types/hooks.d.ts +182 -85
- package/types/instance.d.ts +286 -118
- package/types/logger.d.ts +18 -104
- package/types/plugin.d.ts +10 -4
- package/types/reply.d.ts +18 -12
- package/types/request.d.ts +13 -8
- package/types/route.d.ts +62 -34
- package/types/schema.d.ts +1 -1
- package/types/type-provider.d.ts +99 -0
- package/types/utils.d.ts +1 -1
- package/lib/schema-compilers.js +0 -12
- package/test/emit-warning.test.js +0 -166
package/docs/Reference/Server.md
CHANGED
|
@@ -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: `
|
|
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: `
|
|
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
|
|
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
|
-
|
|
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: `
|
|
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
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
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
|
-
|
|
848
|
-
|
|
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(
|
|
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
|
|
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'
|
|
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 (
|
|
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.
|
|
1192
|
-
|
|
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.
|
|
881
|
-
of it's properties can be configured via `logger` field when
|
|
882
|
-
Fastify's instance. If properties you need aren't exposed,
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
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:
|
|
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
|
|
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
|
|
150
|
-
|
|
151
|
-
Schema validator.
|
|
152
|
-
|
|
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
|
|
241
|
-
parameters in querystring
|
|
242
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
439
|
-
removeAdditional: true,
|
|
415
|
+
removeAdditional: 'all',
|
|
440
416
|
useDefaults: true,
|
|
441
|
-
coerceTypes:
|
|
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('
|
|
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
|
-
`
|
|
516
|
-
error messages. However, the `
|
|
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
|
|
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
|
|
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
|