fastify 3.24.0 → 3.25.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.
- package/README.md +30 -29
- package/docs/{Benchmarking.md → Guides/Benchmarking.md} +14 -5
- package/docs/Guides/Ecosystem.md +513 -0
- package/docs/{Fluent-Schema.md → Guides/Fluent-Schema.md} +16 -7
- package/docs/{Getting-Started.md → Guides/Getting-Started.md} +180 -60
- package/docs/Guides/Index.md +30 -4
- package/docs/{Migration-Guide-V3.md → Guides/Migration-Guide-V3.md} +43 -37
- package/docs/{Plugins-Guide.md → Guides/Plugins-Guide.md} +196 -82
- package/docs/{Recommendations.md → Guides/Recommendations.md} +17 -10
- package/docs/{Serverless.md → Guides/Serverless.md} +200 -42
- package/docs/Guides/Style-Guide.md +246 -0
- package/docs/{Testing.md → Guides/Testing.md} +26 -12
- package/docs/Guides/Write-Plugin.md +102 -0
- package/docs/{ContentTypeParser.md → Reference/ContentTypeParser.md} +68 -30
- package/docs/{Decorators.md → Reference/Decorators.md} +52 -47
- package/docs/{Encapsulation.md → Reference/Encapsulation.md} +3 -3
- package/docs/{Errors.md → Reference/Errors.md} +77 -47
- package/docs/{HTTP2.md → Reference/HTTP2.md} +13 -13
- package/docs/{Hooks.md → Reference/Hooks.md} +157 -70
- package/docs/Reference/Index.md +71 -0
- package/docs/{LTS.md → Reference/LTS.md} +31 -32
- package/docs/{Lifecycle.md → Reference/Lifecycle.md} +15 -7
- package/docs/{Logging.md → Reference/Logging.md} +68 -28
- package/docs/Reference/Middleware.md +78 -0
- package/docs/{Plugins.md → Reference/Plugins.md} +91 -34
- package/docs/{Reply.md → Reference/Reply.md} +205 -94
- package/docs/{Request.md → Reference/Request.md} +32 -16
- package/docs/{Routes.md → Reference/Routes.md} +243 -113
- package/docs/{Server.md → Reference/Server.md} +516 -267
- package/docs/{TypeScript.md → Reference/TypeScript.md} +451 -191
- package/docs/{Validation-and-Serialization.md → Reference/Validation-and-Serialization.md} +178 -86
- package/docs/index.md +24 -0
- package/examples/typescript-server.ts +1 -1
- package/fastify.js +2 -3
- package/lib/contentTypeParser.js +11 -6
- package/lib/decorate.js +6 -3
- package/lib/logger.js +1 -1
- package/lib/route.js +1 -1
- package/lib/server.js +9 -8
- package/package.json +9 -4
- package/test/als.test.js +74 -0
- package/test/constrained-routes.test.js +220 -0
- package/test/custom-parser.test.js +11 -2
- package/test/decorator.test.js +38 -0
- package/test/handler-context.test.js +11 -4
- package/test/http2/closing.test.js +14 -5
- package/test/http2/constraint.test.js +91 -0
- package/test/listen.test.js +36 -22
- package/test/logger.test.js +16 -0
- package/test/maxRequestsPerSocket.test.js +10 -0
- package/test/request-error.test.js +2 -8
- package/test/requestTimeout.test.js +4 -1
- package/test/router-options.test.js +10 -1
- package/test/schema-feature.test.js +146 -0
- package/test/stream.test.js +14 -3
- package/test/trust-proxy.test.js +15 -7
- package/test/types/instance.test-d.ts +52 -1
- package/test/types/request.test-d.ts +7 -1
- package/test/types/route.test-d.ts +21 -0
- package/types/hooks.d.ts +12 -1
- package/types/instance.d.ts +16 -6
- package/types/request.d.ts +4 -1
- package/types/route.d.ts +1 -1
- package/docs/Ecosystem.md +0 -211
- package/docs/Middleware.md +0 -53
- package/docs/Style-Guide.md +0 -185
- package/docs/Write-Plugin.md +0 -58
|
@@ -1,41 +1,59 @@
|
|
|
1
1
|
<h1 align="center">Fastify</h1>
|
|
2
2
|
|
|
3
3
|
## Validation and Serialization
|
|
4
|
-
Fastify uses a schema-based approach, and even if it is not mandatory we
|
|
4
|
+
Fastify uses a schema-based approach, and even if it is not mandatory we
|
|
5
|
+
recommend using [JSON Schema](https://json-schema.org/) to validate your routes
|
|
6
|
+
and serialize your outputs. Internally, Fastify compiles the schema into a
|
|
7
|
+
highly performant function.
|
|
5
8
|
|
|
6
9
|
> ## ⚠ Security Notice
|
|
7
|
-
> Treat the schema definition as application code.
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
13
|
-
>
|
|
14
|
-
>
|
|
15
|
-
>
|
|
16
|
-
> application. If you need to run `async` tasks, use [Fastify's
|
|
10
|
+
> Treat the schema definition as application code. Validation and serialization
|
|
11
|
+
> features dynamically evaluate code with `new Function()`, which is not safe to
|
|
12
|
+
> use with user-provided schemas. See [Ajv](https://npm.im/ajv) and
|
|
13
|
+
> [fast-json-stringify](https://npm.im/fast-json-stringify) for more details.
|
|
14
|
+
>
|
|
15
|
+
> Moreover, the [`$async` Ajv
|
|
16
|
+
> feature](https://ajv.js.org/guide/async-validation.html) should not be used as
|
|
17
|
+
> part of the first validation strategy. This option is used to access Databases
|
|
18
|
+
> and reading them during the validation process may lead to Denial of Service
|
|
19
|
+
> Attacks to your application. If you need to run `async` tasks, use [Fastify's
|
|
20
|
+
> hooks](./Hooks.md) instead after validation completes, such as `preHandler`.
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
### Core concepts
|
|
20
|
-
The validation and the serialization tasks are processed by two different, and
|
|
21
|
-
|
|
22
|
-
- [
|
|
24
|
+
The validation and the serialization tasks are processed by two different, and
|
|
25
|
+
customizable, actors:
|
|
26
|
+
- [Ajv v6](https://www.npmjs.com/package/ajv/v/6.12.6) for the validation of a
|
|
27
|
+
request
|
|
28
|
+
- [fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify) for
|
|
29
|
+
the serialization of a response's body
|
|
23
30
|
|
|
24
|
-
These two separate entities share only the JSON schemas added to Fastify's
|
|
31
|
+
These two separate entities share only the JSON schemas added to Fastify's
|
|
32
|
+
instance through `.addSchema(schema)`.
|
|
25
33
|
|
|
26
|
-
<a name="shared-schema"></a>
|
|
27
34
|
#### Adding a shared schema
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
+ `myField: { $ref: '
|
|
35
|
+
<a id="shared-schema"></a>
|
|
36
|
+
|
|
37
|
+
Thanks to the `addSchema` API, you can add multiple schemas to the Fastify
|
|
38
|
+
instance and then reuse them in multiple parts of your application. As usual,
|
|
39
|
+
this API is encapsulated.
|
|
40
|
+
|
|
41
|
+
The shared schemas can be reused through the JSON Schema
|
|
42
|
+
[**`$ref`**](https://tools.ietf.org/html/draft-handrews-json-schema-01#section-8)
|
|
43
|
+
keyword. Here an overview of _how_ references work:
|
|
44
|
+
|
|
45
|
+
+ `myField: { $ref: '#foo'}` will search for field with `$id: '#foo'` inside the
|
|
46
|
+
current schema
|
|
47
|
+
+ `myField: { $ref: '#/definitions/foo'}` will search for field
|
|
48
|
+
`definitions.foo` inside the current schema
|
|
49
|
+
+ `myField: { $ref: 'http://url.com/sh.json#'}` will search for a shared schema
|
|
50
|
+
added with `$id: 'http://url.com/sh.json'`
|
|
51
|
+
+ `myField: { $ref: 'http://url.com/sh.json#/definitions/foo'}` will search for
|
|
52
|
+
a shared schema added with `$id: 'http://url.com/sh.json'` and will use the
|
|
53
|
+
field `definitions.foo`
|
|
54
|
+
+ `myField: { $ref: 'http://url.com/sh.json#foo'}` will search for a shared
|
|
55
|
+
schema added with `$id: 'http://url.com/sh.json'` and it will look inside of
|
|
56
|
+
it for object with `$id: '#foo'`
|
|
39
57
|
|
|
40
58
|
|
|
41
59
|
**Simple usage:**
|
|
@@ -80,12 +98,12 @@ fastify.post('/', {
|
|
|
80
98
|
})
|
|
81
99
|
```
|
|
82
100
|
|
|
83
|
-
<a name="get-shared-schema"></a>
|
|
84
101
|
#### Retrieving the shared schemas
|
|
102
|
+
<a id="get-shared-schema"></a>
|
|
85
103
|
|
|
86
|
-
If the validator and the serializer are customized, the `.addSchema` method will
|
|
87
|
-
controlled by Fastify.
|
|
88
|
-
|
|
104
|
+
If the validator and the serializer are customized, the `.addSchema` method will
|
|
105
|
+
not be useful since the actors are no longer controlled by Fastify. To access
|
|
106
|
+
the schemas added to the Fastify instance, you can simply use `.getSchemas()`:
|
|
89
107
|
|
|
90
108
|
```js
|
|
91
109
|
fastify.addSchema({
|
|
@@ -100,7 +118,8 @@ const mySchemas = fastify.getSchemas()
|
|
|
100
118
|
const mySchema = fastify.getSchema('schemaId')
|
|
101
119
|
```
|
|
102
120
|
|
|
103
|
-
As usual, the function `getSchemas` is encapsulated and returns the shared
|
|
121
|
+
As usual, the function `getSchemas` is encapsulated and returns the shared
|
|
122
|
+
schemas available in the selected scope:
|
|
104
123
|
|
|
105
124
|
```js
|
|
106
125
|
fastify.addSchema({ $id: 'one', my: 'hello' })
|
|
@@ -124,18 +143,26 @@ fastify.register((instance, opts, done) => {
|
|
|
124
143
|
|
|
125
144
|
|
|
126
145
|
### Validation
|
|
127
|
-
The route validation internally relies upon [Ajv
|
|
128
|
-
|
|
146
|
+
The route validation internally relies upon [Ajv
|
|
147
|
+
v6](https://www.npmjs.com/package/ajv/v/6.12.6) which is a high-performance JSON
|
|
148
|
+
Schema validator. Validating the input is very easy: just add the fields that
|
|
149
|
+
you need inside the route schema, and you are done!
|
|
129
150
|
|
|
130
151
|
The supported validations are:
|
|
131
|
-
- `body`: validates the body of the request if it is a POST, PUT, or PATCH
|
|
152
|
+
- `body`: validates the body of the request if it is a POST, PUT, or PATCH
|
|
153
|
+
method.
|
|
132
154
|
- `querystring` or `query`: validates the query string.
|
|
133
155
|
- `params`: validates the route params.
|
|
134
156
|
- `headers`: validates the request headers.
|
|
135
157
|
|
|
136
|
-
All the validations can be a complete JSON Schema object (with a `type` property
|
|
158
|
+
All the validations can be a complete JSON Schema object (with a `type` property
|
|
159
|
+
of `'object'` and a `'properties'` object containing parameters) or a simpler
|
|
160
|
+
variation in which the `type` and `properties` attributes are forgone and the
|
|
161
|
+
parameters are listed at the top level (see the example below).
|
|
137
162
|
|
|
138
|
-
> ℹ If you need to use the lastest version of Ajv (v8) you should read how to do
|
|
163
|
+
> ℹ If you need to use the lastest version of Ajv (v8) you should read how to do
|
|
164
|
+
> it in the [`schemaController`](./Server.md#schema-controller) section. It is
|
|
165
|
+
> explained the easier way to avoid to implement a custom validator.
|
|
139
166
|
|
|
140
167
|
Example:
|
|
141
168
|
```js
|
|
@@ -202,9 +229,15 @@ const schema = {
|
|
|
202
229
|
fastify.post('/the/url', { schema }, handler)
|
|
203
230
|
```
|
|
204
231
|
|
|
205
|
-
*Note that Ajv will try to
|
|
232
|
+
*Note that Ajv will try to
|
|
233
|
+
[coerce](https://github.com/epoberezkin/ajv#coercing-data-types) the values to
|
|
234
|
+
the types specified in your schema `type` keywords, both to pass the validation
|
|
235
|
+
and to use the correctly typed data afterwards.*
|
|
206
236
|
|
|
207
|
-
The Ajv default configuration in Fastify doesn't support coercing array
|
|
237
|
+
The Ajv default configuration in Fastify doesn't support coercing array
|
|
238
|
+
parameters in querystring. However, Fastify allows
|
|
239
|
+
[`customOptions`](./Server.md#ajv) in Ajv instance. The `coerceTypes: 'array'`
|
|
240
|
+
will coerce one parameter to a single element in array. Example:
|
|
208
241
|
|
|
209
242
|
```js
|
|
210
243
|
const opts = {
|
|
@@ -259,9 +292,11 @@ curl -X GET "http://localhost:3000/?ids=1
|
|
|
259
292
|
{"params":{"hello":["1"]}}
|
|
260
293
|
```
|
|
261
294
|
|
|
262
|
-
You can also specify a custom schema validator for each parameter type (body,
|
|
295
|
+
You can also specify a custom schema validator for each parameter type (body,
|
|
296
|
+
querystring, params, headers).
|
|
263
297
|
|
|
264
|
-
For example, the following code disable type coercion only for the `body`
|
|
298
|
+
For example, the following code disable type coercion only for the `body`
|
|
299
|
+
parameters, changing the ajv default options:
|
|
265
300
|
|
|
266
301
|
```js
|
|
267
302
|
const schemaCompilers = {
|
|
@@ -301,13 +336,13 @@ server.setValidatorCompiler(req => {
|
|
|
301
336
|
|
|
302
337
|
For further information see [here](https://ajv.js.org/coercion.html)
|
|
303
338
|
|
|
304
|
-
<a name="ajv-plugins"></a>
|
|
305
339
|
#### Ajv Plugins
|
|
340
|
+
<a id="ajv-plugins"></a>
|
|
306
341
|
|
|
307
|
-
You can provide a list of plugins you want to use with the default `ajv`
|
|
308
|
-
Note that the plugin must be **compatible with Ajv v6**.
|
|
342
|
+
You can provide a list of plugins you want to use with the default `ajv`
|
|
343
|
+
instance. Note that the plugin must be **compatible with Ajv v6**.
|
|
309
344
|
|
|
310
|
-
> Refer to [`ajv options`](Server.md#ajv) to check plugins format
|
|
345
|
+
> Refer to [`ajv options`](./Server.md#ajv) to check plugins format
|
|
311
346
|
|
|
312
347
|
```js
|
|
313
348
|
const fastify = require('fastify')({
|
|
@@ -365,14 +400,18 @@ fastify.post('/foo', {
|
|
|
365
400
|
})
|
|
366
401
|
```
|
|
367
402
|
|
|
368
|
-
<a name="schema-validator"></a>
|
|
369
403
|
#### Validator Compiler
|
|
404
|
+
<a id="schema-validator"></a>
|
|
370
405
|
|
|
371
|
-
The `validatorCompiler` is a function that returns a function that validates the
|
|
372
|
-
|
|
373
|
-
|
|
406
|
+
The `validatorCompiler` is a function that returns a function that validates the
|
|
407
|
+
body, URL parameters, headers, and query string. The default
|
|
408
|
+
`validatorCompiler` returns a function that implements the
|
|
409
|
+
[ajv](https://ajv.js.org/) validation interface. Fastify uses it internally to
|
|
410
|
+
speed the validation up.
|
|
374
411
|
|
|
375
|
-
Fastify's [baseline ajv
|
|
412
|
+
Fastify's [baseline ajv
|
|
413
|
+
configuration](https://github.com/epoberezkin/ajv#options-to-modify-validated-data)
|
|
414
|
+
is:
|
|
376
415
|
|
|
377
416
|
```js
|
|
378
417
|
{
|
|
@@ -383,9 +422,11 @@ Fastify's [baseline ajv configuration](https://github.com/epoberezkin/ajv#option
|
|
|
383
422
|
}
|
|
384
423
|
```
|
|
385
424
|
|
|
386
|
-
This baseline configuration can be modified by providing
|
|
425
|
+
This baseline configuration can be modified by providing
|
|
426
|
+
[`ajv.customOptions`](./Server.md#factory-ajv) to your Fastify factory.
|
|
387
427
|
|
|
388
|
-
If you want to change or set additional config options, you will need to create
|
|
428
|
+
If you want to change or set additional config options, you will need to create
|
|
429
|
+
your own instance and override the existing one like:
|
|
389
430
|
|
|
390
431
|
```js
|
|
391
432
|
const fastify = require('fastify')()
|
|
@@ -403,12 +444,17 @@ fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
|
|
|
403
444
|
return ajv.compile(schema)
|
|
404
445
|
})
|
|
405
446
|
```
|
|
406
|
-
_**Note:** If you use a custom instance of any validator (even Ajv), you have to
|
|
447
|
+
_**Note:** If you use a custom instance of any validator (even Ajv), you have to
|
|
448
|
+
add schemas to the validator instead of Fastify, since Fastify's default
|
|
449
|
+
validator is no longer used, and Fastify's `addSchema` method has no idea what
|
|
450
|
+
validator you are using._
|
|
407
451
|
|
|
408
|
-
<a name="using-other-validation-libraries"></a>
|
|
409
452
|
##### Using other validation libraries
|
|
453
|
+
<a id="using-other-validation-libraries"></a>
|
|
410
454
|
|
|
411
|
-
The `setValidatorCompiler` function makes it easy to substitute `ajv` with
|
|
455
|
+
The `setValidatorCompiler` function makes it easy to substitute `ajv` with
|
|
456
|
+
almost any Javascript validation library ([joi](https://github.com/hapijs/joi/),
|
|
457
|
+
[yup](https://github.com/jquense/yup/), ...) or a custom one:
|
|
412
458
|
|
|
413
459
|
```js
|
|
414
460
|
const Joi = require('@hapi/joi')
|
|
@@ -461,19 +507,32 @@ fastify.post('/the/url', {
|
|
|
461
507
|
|
|
462
508
|
##### Validation messages with other validation libraries
|
|
463
509
|
|
|
464
|
-
Fastify's validation error messages are tightly coupled to the default
|
|
510
|
+
Fastify's validation error messages are tightly coupled to the default
|
|
511
|
+
validation engine: errors returned from `ajv` are eventually run through the
|
|
512
|
+
`schemaErrorsText` function which is responsible for building human-friendly
|
|
513
|
+
error messages. However, the `schemaErrorsText` function is written with `ajv`
|
|
514
|
+
in mind : as a result, you may run into odd or incomplete error messages when
|
|
515
|
+
using other validation libraries.
|
|
465
516
|
|
|
466
517
|
To circumvent this issue, you have 2 main options :
|
|
467
518
|
|
|
468
|
-
1. make sure your validation function (returned by your custom `schemaCompiler`)
|
|
469
|
-
|
|
519
|
+
1. make sure your validation function (returned by your custom `schemaCompiler`)
|
|
520
|
+
returns errors in the exact same structure and format as `ajv` (although this
|
|
521
|
+
could prove to be difficult and tricky due to differences between validation
|
|
522
|
+
engines)
|
|
523
|
+
2. or use a custom `errorHandler` to intercept and format your 'custom'
|
|
524
|
+
validation errors
|
|
470
525
|
|
|
471
|
-
To help you in writing a custom `errorHandler`, Fastify adds 2 properties to all
|
|
526
|
+
To help you in writing a custom `errorHandler`, Fastify adds 2 properties to all
|
|
527
|
+
validation errors:
|
|
472
528
|
|
|
473
|
-
* validation: the content of the `error` property of the object returned by the
|
|
474
|
-
|
|
529
|
+
* validation: the content of the `error` property of the object returned by the
|
|
530
|
+
validation function (returned by your custom `schemaCompiler`)
|
|
531
|
+
* validationContext: the 'context' (body, params, query, headers) where the
|
|
532
|
+
validation error occurred
|
|
475
533
|
|
|
476
|
-
A very contrived example of such a custom `errorHandler` handling validation
|
|
534
|
+
A very contrived example of such a custom `errorHandler` handling validation
|
|
535
|
+
errors is shown below:
|
|
477
536
|
|
|
478
537
|
```js
|
|
479
538
|
const errorHandler = (error, request, reply) => {
|
|
@@ -503,10 +562,15 @@ const errorHandler = (error, request, reply) => {
|
|
|
503
562
|
}
|
|
504
563
|
```
|
|
505
564
|
|
|
506
|
-
<a name="serialization"></a>
|
|
507
565
|
### Serialization
|
|
508
|
-
|
|
509
|
-
|
|
566
|
+
<a id="serialization"></a>
|
|
567
|
+
|
|
568
|
+
Usually, you will send your data to the clients as JSON, and Fastify has a
|
|
569
|
+
powerful tool to help you,
|
|
570
|
+
[fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify), which
|
|
571
|
+
is used if you have provided an output schema in the route options. We encourage
|
|
572
|
+
you to use an output schema, as it can drastically increase throughput and help
|
|
573
|
+
prevent accidental disclosure of sensitive information.
|
|
510
574
|
|
|
511
575
|
Example:
|
|
512
576
|
```js
|
|
@@ -525,7 +589,8 @@ const schema = {
|
|
|
525
589
|
fastify.post('/the/url', { schema }, handler)
|
|
526
590
|
```
|
|
527
591
|
|
|
528
|
-
As you can see, the response schema is based on the status code. If you want to
|
|
592
|
+
As you can see, the response schema is based on the status code. If you want to
|
|
593
|
+
use the same schema for multiple status codes, you can use `'2xx'`, for example:
|
|
529
594
|
```js
|
|
530
595
|
const schema = {
|
|
531
596
|
response: {
|
|
@@ -546,10 +611,13 @@ const schema = {
|
|
|
546
611
|
fastify.post('/the/url', { schema }, handler)
|
|
547
612
|
```
|
|
548
613
|
|
|
549
|
-
<a name="schema-serializer"></a>
|
|
550
614
|
#### Serializer Compiler
|
|
615
|
+
<a id="schema-serializer"></a>
|
|
551
616
|
|
|
552
|
-
The `serializerCompiler` is a function that returns a function that must return
|
|
617
|
+
The `serializerCompiler` is a function that returns a function that must return
|
|
618
|
+
a string from an input object. When you define a response JSON Schema, you can
|
|
619
|
+
change the default serialization method by providing a function to serialize
|
|
620
|
+
every route where you do.
|
|
553
621
|
|
|
554
622
|
```js
|
|
555
623
|
fastify.setSerializerCompiler(({ schema, method, url, httpStatus }) => {
|
|
@@ -571,10 +639,13 @@ fastify.get('/user', {
|
|
|
571
639
|
})
|
|
572
640
|
```
|
|
573
641
|
|
|
574
|
-
*If you need a custom serializer in a very specific part of your code, you can
|
|
642
|
+
*If you need a custom serializer in a very specific part of your code, you can
|
|
643
|
+
set one with [`reply.serializer(...)`](./Reply.md#serializerfunc).*
|
|
575
644
|
|
|
576
645
|
### Error Handling
|
|
577
|
-
When schema validation fails for a request, Fastify will automatically return a
|
|
646
|
+
When schema validation fails for a request, Fastify will automatically return a
|
|
647
|
+
status 400 response including the result from the validator in the payload. As
|
|
648
|
+
an example, if you have the following schema for your route
|
|
578
649
|
|
|
579
650
|
```js
|
|
580
651
|
const schema = {
|
|
@@ -588,7 +659,8 @@ const schema = {
|
|
|
588
659
|
}
|
|
589
660
|
```
|
|
590
661
|
|
|
591
|
-
and fail to satisfy it, the route will immediately return a response with the
|
|
662
|
+
and fail to satisfy it, the route will immediately return a response with the
|
|
663
|
+
following payload
|
|
592
664
|
|
|
593
665
|
```js
|
|
594
666
|
{
|
|
@@ -598,7 +670,10 @@ and fail to satisfy it, the route will immediately return a response with the fo
|
|
|
598
670
|
}
|
|
599
671
|
```
|
|
600
672
|
|
|
601
|
-
If you want to handle errors inside the route, you can specify the
|
|
673
|
+
If you want to handle errors inside the route, you can specify the
|
|
674
|
+
`attachValidation` option for your route. If there is a _validation error_, the
|
|
675
|
+
`validationError` property of the request will contain the `Error` object with
|
|
676
|
+
the raw `validation` result as shown below
|
|
602
677
|
|
|
603
678
|
```js
|
|
604
679
|
const fastify = Fastify()
|
|
@@ -613,11 +688,13 @@ fastify.post('/', { schema, attachValidation: true }, function (req, reply) {
|
|
|
613
688
|
|
|
614
689
|
#### `schemaErrorFormatter`
|
|
615
690
|
|
|
616
|
-
If you want to format errors yourself, you can provide a sync function that must
|
|
617
|
-
|
|
691
|
+
If you want to format errors yourself, you can provide a sync function that must
|
|
692
|
+
return an error as the `schemaErrorFormatter` option to Fastify when
|
|
693
|
+
instantiating. The context function will be the Fastify server instance.
|
|
618
694
|
|
|
619
695
|
`errors` is an array of Fastify schema errors `FastifySchemaValidationError`.
|
|
620
|
-
`dataVar` is the currently validated part of the schema. (params | body |
|
|
696
|
+
`dataVar` is the currently validated part of the schema. (params | body |
|
|
697
|
+
querystring | headers).
|
|
621
698
|
|
|
622
699
|
```js
|
|
623
700
|
const fastify = Fastify({
|
|
@@ -635,7 +712,9 @@ fastify.setSchemaErrorFormatter(function (errors, dataVar) {
|
|
|
635
712
|
})
|
|
636
713
|
```
|
|
637
714
|
|
|
638
|
-
You can also use
|
|
715
|
+
You can also use
|
|
716
|
+
[setErrorHandler](./Server.md#seterrorhandler) to
|
|
717
|
+
define a custom response for validation errors such as
|
|
639
718
|
|
|
640
719
|
```js
|
|
641
720
|
fastify.setErrorHandler(function (error, request, reply) {
|
|
@@ -645,11 +724,18 @@ fastify.setErrorHandler(function (error, request, reply) {
|
|
|
645
724
|
})
|
|
646
725
|
```
|
|
647
726
|
|
|
648
|
-
If you want custom error response in schema without headaches and quickly, you
|
|
649
|
-
|
|
727
|
+
If you want custom error response in schema without headaches and quickly, you
|
|
728
|
+
can take a look at [`ajv-errors`](https://github.com/epoberezkin/ajv-errors).
|
|
729
|
+
Check out the
|
|
730
|
+
[example](https://github.com/fastify/example/blob/HEAD/validation-messages/custom-errors-messages.js)
|
|
731
|
+
usage.
|
|
732
|
+
> Make sure to install version 1.0.1 of `ajv-errors`, because later versions of
|
|
733
|
+
> it are not compatible with AJV v6 (the version shipped by Fastify v3).
|
|
650
734
|
|
|
651
|
-
Below is an example showing how to add **custom error messages for each
|
|
652
|
-
|
|
735
|
+
Below is an example showing how to add **custom error messages for each
|
|
736
|
+
property** of a schema by supplying custom AJV options. Inline comments in the
|
|
737
|
+
schema below describe how to configure it to show a different error message for
|
|
738
|
+
each case:
|
|
653
739
|
|
|
654
740
|
```js
|
|
655
741
|
const fastify = Fastify({
|
|
@@ -699,7 +785,8 @@ fastify.post('/', { schema, }, (request, reply) => {
|
|
|
699
785
|
})
|
|
700
786
|
```
|
|
701
787
|
|
|
702
|
-
If you want to return localized error messages, take a look at
|
|
788
|
+
If you want to return localized error messages, take a look at
|
|
789
|
+
[ajv-i18n](https://github.com/epoberezkin/ajv-i18n)
|
|
703
790
|
|
|
704
791
|
```js
|
|
705
792
|
const localize = require('ajv-i18n')
|
|
@@ -734,7 +821,8 @@ fastify.setErrorHandler(function (error, request, reply) {
|
|
|
734
821
|
### JSON Schema support
|
|
735
822
|
|
|
736
823
|
JSON Schema has some type of utilities in order to optimize your schemas that,
|
|
737
|
-
in conjunction with Fastify's shared schema, let you reuse all your schemas
|
|
824
|
+
in conjunction with Fastify's shared schema, let you reuse all your schemas
|
|
825
|
+
easily.
|
|
738
826
|
|
|
739
827
|
| Use Case | Validator | Serializer |
|
|
740
828
|
|-----------------------------------|-----------|------------|
|
|
@@ -836,12 +924,16 @@ const refToSharedSchemaDefinitions = {
|
|
|
836
924
|
}
|
|
837
925
|
```
|
|
838
926
|
|
|
839
|
-
<a name="resources"></a>
|
|
840
927
|
### Resources
|
|
928
|
+
<a id="resources"></a>
|
|
929
|
+
|
|
841
930
|
- [JSON Schema](https://json-schema.org/)
|
|
842
|
-
- [Understanding JSON
|
|
843
|
-
|
|
931
|
+
- [Understanding JSON
|
|
932
|
+
Schema](https://spacetelescope.github.io/understanding-json-schema/)
|
|
933
|
+
- [fast-json-stringify
|
|
934
|
+
documentation](https://github.com/fastify/fast-json-stringify)
|
|
844
935
|
- [Ajv documentation](https://github.com/epoberezkin/ajv/blob/master/README.md)
|
|
845
936
|
- [Ajv i18n](https://github.com/epoberezkin/ajv-i18n)
|
|
846
937
|
- [Ajv custom errors](https://github.com/epoberezkin/ajv-errors)
|
|
847
|
-
- Custom error handling with core methods with error file dumping
|
|
938
|
+
- Custom error handling with core methods with error file dumping
|
|
939
|
+
[example](https://github.com/fastify/example/tree/master/validation-messages)
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<h1 align="center">Fastify</h1>
|
|
2
|
+
|
|
3
|
+
The documentation for Fastify is split into two categories:
|
|
4
|
+
|
|
5
|
+
- [Reference documentation](./Reference/Index.md)
|
|
6
|
+
- [Guides](./Guides/Index.md)
|
|
7
|
+
|
|
8
|
+
The reference documentation utilizes a very formal style in an effort to document
|
|
9
|
+
Fastify's API and implementation details thoroughly for the developer who needs
|
|
10
|
+
such. The guides category utilizes an informal, educational, style as a means to
|
|
11
|
+
introduce newcomers to core, and advanced, Fastify concepts.
|
|
12
|
+
|
|
13
|
+
## Where To Start
|
|
14
|
+
|
|
15
|
+
Complete newcomers to Fastify should first read our [Getting
|
|
16
|
+
Started](./Guides/Getting-Started.md) guide.
|
|
17
|
+
|
|
18
|
+
Developers experienced with Fastify should consult the [reference
|
|
19
|
+
documentation](./Reference/index.md) directly to find the topic they are seeking
|
|
20
|
+
more information about.
|
|
21
|
+
|
|
22
|
+
## Additional Documentation
|
|
23
|
+
|
|
24
|
+
- Fastify's [Long Term Support (LTS)](./Reference/LTS.md) policy
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '3.
|
|
3
|
+
const VERSION = '3.25.2'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('http')
|
|
@@ -631,8 +631,7 @@ function fastify (options) {
|
|
|
631
631
|
function setSchemaController (schemaControllerOpts) {
|
|
632
632
|
throwIfAlreadyStarted('Cannot call "setSchemaController" when fastify instance is already started!')
|
|
633
633
|
const old = this[kSchemaController]
|
|
634
|
-
const
|
|
635
|
-
const schemaController = SchemaController.buildSchemaController(parent, Object.assign({}, old.opts, schemaControllerOpts))
|
|
634
|
+
const schemaController = SchemaController.buildSchemaController(old, Object.assign({}, old.opts, schemaControllerOpts))
|
|
636
635
|
this[kSchemaController] = schemaController
|
|
637
636
|
this.getSchema = schemaController.getSchema.bind(schemaController)
|
|
638
637
|
this.getSchemas = schemaController.getSchemas.bind(schemaController)
|
package/lib/contentTypeParser.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { AsyncResource } = require('async_hooks')
|
|
3
4
|
let lru = require('tiny-lru')
|
|
4
5
|
// Needed to handle Webpack and faux modules
|
|
5
6
|
// See https://github.com/fastify/fastify/issues/2356
|
|
@@ -137,6 +138,7 @@ ContentTypeParser.prototype.remove = function (contentType) {
|
|
|
137
138
|
|
|
138
139
|
ContentTypeParser.prototype.run = function (contentType, handler, request, reply) {
|
|
139
140
|
const parser = this.cache.get(contentType) || this.getParser(contentType)
|
|
141
|
+
const resource = new AsyncResource('content-type-parser:run', request)
|
|
140
142
|
|
|
141
143
|
if (parser === undefined) {
|
|
142
144
|
reply.send(new FST_ERR_CTP_INVALID_MEDIA_TYPE(contentType))
|
|
@@ -163,12 +165,15 @@ ContentTypeParser.prototype.run = function (contentType, handler, request, reply
|
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
function done (error, body) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
// We cannot use resource.bind() because it is broken in node v12.
|
|
169
|
+
resource.runInAsyncScope(() => {
|
|
170
|
+
if (error) {
|
|
171
|
+
reply.send(error)
|
|
172
|
+
} else {
|
|
173
|
+
request.body = body
|
|
174
|
+
handler(request, reply)
|
|
175
|
+
}
|
|
176
|
+
})
|
|
172
177
|
}
|
|
173
178
|
}
|
|
174
179
|
|
package/lib/decorate.js
CHANGED
|
@@ -40,7 +40,7 @@ function decorateConstructor (konstructor, name, fn, dependencies) {
|
|
|
40
40
|
throw new FST_ERR_DEC_ALREADY_PRESENT(name)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
checkDependencies(
|
|
43
|
+
checkDependencies(konstructor, name, dependencies)
|
|
44
44
|
|
|
45
45
|
if (fn && (typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
|
|
46
46
|
Object.defineProperty(instance, name, {
|
|
@@ -68,14 +68,17 @@ function decorateFastify (name, fn, dependencies) {
|
|
|
68
68
|
|
|
69
69
|
function checkExistence (instance, name) {
|
|
70
70
|
if (name) {
|
|
71
|
-
return name in instance
|
|
71
|
+
return name in instance || (instance.prototype && name in instance.prototype) || hasKey(instance, name)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return instance in this
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function hasKey (fn, name) {
|
|
78
|
-
|
|
78
|
+
if (fn.props) {
|
|
79
|
+
return fn.props.find(({ key }) => key === name)
|
|
80
|
+
}
|
|
81
|
+
return false
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
function checkRequestExistence (name) {
|
package/lib/logger.js
CHANGED
|
@@ -50,7 +50,7 @@ const serializers = {
|
|
|
50
50
|
return {
|
|
51
51
|
method: req.method,
|
|
52
52
|
url: req.url,
|
|
53
|
-
version: req.headers['accept-version'],
|
|
53
|
+
version: req.headers && req.headers['accept-version'],
|
|
54
54
|
hostname: req.hostname,
|
|
55
55
|
remoteAddress: req.ip,
|
|
56
56
|
remotePort: req.socket ? req.socket.remotePort : undefined
|
package/lib/route.js
CHANGED
|
@@ -248,7 +248,7 @@ function buildRouting (options) {
|
|
|
248
248
|
opts.schemaErrorFormatter || this[kSchemaErrorFormatter]
|
|
249
249
|
)
|
|
250
250
|
|
|
251
|
-
const headRouteExists = router.find('HEAD', url) != null
|
|
251
|
+
const headRouteExists = router.find('HEAD', url, constraints) != null
|
|
252
252
|
|
|
253
253
|
try {
|
|
254
254
|
router.on(opts.method, opts.url, { constraints }, routeHandler, context)
|
package/lib/server.js
CHANGED
|
@@ -14,19 +14,20 @@ function createServer (options, httpHandler) {
|
|
|
14
14
|
let server = null
|
|
15
15
|
if (options.serverFactory) {
|
|
16
16
|
server = options.serverFactory(httpHandler, options)
|
|
17
|
-
} else if (options.
|
|
18
|
-
if (options.
|
|
17
|
+
} else if (options.http2) {
|
|
18
|
+
if (options.https) {
|
|
19
19
|
server = http2().createSecureServer(options.https, httpHandler)
|
|
20
|
-
server.on('session', sessionTimeout(options.http2SessionTimeout))
|
|
21
20
|
} else {
|
|
22
|
-
server =
|
|
23
|
-
server.keepAliveTimeout = options.keepAliveTimeout
|
|
21
|
+
server = http2().createServer(httpHandler)
|
|
24
22
|
}
|
|
25
|
-
} else if (options.http2) {
|
|
26
|
-
server = http2().createServer(httpHandler)
|
|
27
23
|
server.on('session', sessionTimeout(options.http2SessionTimeout))
|
|
28
24
|
} else {
|
|
29
|
-
|
|
25
|
+
// this is http1
|
|
26
|
+
if (options.https) {
|
|
27
|
+
server = https.createServer(options.https, httpHandler)
|
|
28
|
+
} else {
|
|
29
|
+
server = http.createServer(httpHandler)
|
|
30
|
+
}
|
|
30
31
|
server.keepAliveTimeout = options.keepAliveTimeout
|
|
31
32
|
server.requestTimeout = options.requestTimeout
|
|
32
33
|
// we treat zero as null
|