fastify 3.19.1 → 3.20.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/docs/ContentTypeParser.md +56 -2
- package/docs/Decorators.md +3 -0
- package/docs/Ecosystem.md +5 -1
- package/docs/Getting-Started.md +2 -2
- package/docs/Reply.md +6 -5
- package/docs/Request.md +20 -1
- package/docs/Routes.md +3 -3
- package/docs/Server.md +7 -5
- package/docs/TypeScript.md +3 -3
- package/fastify.d.ts +4 -2
- package/fastify.js +28 -6
- package/lib/contentTypeParser.js +46 -1
- package/lib/logger.js +1 -1
- package/lib/pluginUtils.js +3 -1
- package/lib/reply.js +6 -2
- package/lib/request.js +6 -0
- package/lib/route.js +6 -3
- package/package.json +4 -4
- package/test/async-await.test.js +73 -0
- package/test/content-parser.test.js +76 -0
- package/test/custom-parser.test.js +203 -0
- package/test/internals/version.test.js +43 -0
- package/test/request-error.test.js +72 -0
- package/test/route.test.js +56 -0
- package/test/schema-special-usage.test.js +32 -0
- package/test/types/content-type-parser.test-d.ts +8 -0
- package/test/types/fastify.test-d.ts +16 -0
- package/test/types/instance.test-d.ts +40 -2
- package/test/types/logger.test-d.ts +23 -1
- package/test/types/reply.test-d.ts +2 -0
- package/test/types/request.test-d.ts +4 -0
- package/types/content-type-parser.d.ts +4 -0
- package/types/instance.d.ts +37 -6
- package/types/logger.d.ts +1 -0
- package/types/reply.d.ts +2 -0
- package/types/request.d.ts +2 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">Fastify</h1>
|
|
2
2
|
|
|
3
3
|
## `Content-Type` Parser
|
|
4
|
-
Natively, Fastify only supports `'application/json'` and `'text/plain'` content types. The default charset is `utf-8`. If you need to support different content types, you can use the `addContentTypeParser` API. *The default JSON and/or plain text parser can be changed.*
|
|
4
|
+
Natively, Fastify only supports `'application/json'` and `'text/plain'` content types. The default charset is `utf-8`. If you need to support different content types, you can use the `addContentTypeParser` API. *The default JSON and/or plain text parser can be changed or removed.*
|
|
5
5
|
|
|
6
6
|
*Note: If you decide to specify your own content type with the `Content-Type` header, UTF-8 will not be the default. Be sure to include UTF-8 like this `text/html; charset=utf-8`.*
|
|
7
7
|
|
|
@@ -56,7 +56,11 @@ fastify.addContentTypeParser('application/vnd.custom', (request, body, done) =>
|
|
|
56
56
|
fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Besides the `addContentTypeParser` API there are further APIs that can be used. These are `hasContentTypeParser`, `removeContentTypeParser` and `removeAllContentTypeParsers`.
|
|
60
|
+
|
|
61
|
+
#### hasContentTypeParser
|
|
62
|
+
|
|
63
|
+
You can use the `hasContentTypeParser` API to find if a specific content type parser already exists.
|
|
60
64
|
|
|
61
65
|
```js
|
|
62
66
|
if (!fastify.hasContentTypeParser('application/jsoff')){
|
|
@@ -68,6 +72,40 @@ if (!fastify.hasContentTypeParser('application/jsoff')){
|
|
|
68
72
|
}
|
|
69
73
|
```
|
|
70
74
|
|
|
75
|
+
#### removeContentTypeParser
|
|
76
|
+
|
|
77
|
+
With `removeContentTypeParser` a single or an array of content types can be removed. The method supports `string` and
|
|
78
|
+
`RegExp` content types.
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
fastify.addContentTypeParser('text/xml', function (request, payload, done) {
|
|
82
|
+
xmlParser(payload, function (err, body) {
|
|
83
|
+
done(err, body)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// Removes the both built-in content type parsers so that only the content type parser for text/html is available
|
|
88
|
+
fastiy.removeContentTypeParser(['application/json', 'text/plain'])
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### removeAllContentTypeParsers
|
|
92
|
+
|
|
93
|
+
In the example from just above, it is noticeable that we need to specify each content type that we want to remove.
|
|
94
|
+
To solve this problem Fastify provides the `removeAllContentTypeParsers` API. This can be used to remove all currently existing content type parsers.
|
|
95
|
+
In the example below we achieve exactly the same as in the example above except that we do not need to specify each content type to delete.
|
|
96
|
+
Just like `removeContentTypeParser`, this API supports encapsulation. The API is especially useful if you want to register a
|
|
97
|
+
[catch-all content type parser](#Catch-All) that should be executed for every content type and the built-in parsers should be ignored as well.
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
fastiy.removeAllContentTypeParsers()
|
|
101
|
+
|
|
102
|
+
fastify.addContentTypeParser('text/xml', function (request, payload, done) {
|
|
103
|
+
xmlParser(payload, function (err, body) {
|
|
104
|
+
done(err, body)
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
71
109
|
**Notice**: The old syntaxes `function(req, done)` and `async function(req)` for the parser are still supported but they are deprecated.
|
|
72
110
|
|
|
73
111
|
#### Body Parser
|
|
@@ -140,3 +178,19 @@ fastify.route({
|
|
|
140
178
|
```
|
|
141
179
|
|
|
142
180
|
For piping file uploads you may want to check out [this plugin](https://github.com/fastify/fastify-multipart).
|
|
181
|
+
|
|
182
|
+
If you really want the content type parser to be executed on all content types and not only on those that don't have a
|
|
183
|
+
specific one, you should call the `removeAllContentTypeParsers` method first.
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
// Without this call, the request body with the content type application/json would be processed by the built in json parser
|
|
187
|
+
fastify.removeAllContentTypeParsers()
|
|
188
|
+
|
|
189
|
+
fastify.addContentTypeParser('*', function (request, payload, done) {
|
|
190
|
+
var data = ''
|
|
191
|
+
payload.on('data', chunk => { data += chunk })
|
|
192
|
+
payload.on('end', () => {
|
|
193
|
+
done(null, data)
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
```
|
package/docs/Decorators.md
CHANGED
|
@@ -117,6 +117,9 @@ upon "greet" and "log" decorators:
|
|
|
117
117
|
fastify.decorate('utility', fn, ['greet', 'log'])
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
Note: using an arrow function will break the binding of `this` to the
|
|
121
|
+
`FastifyInstance`.
|
|
122
|
+
|
|
120
123
|
If a dependency is not satisfied, the `decorate` method will throw an exception.
|
|
121
124
|
The dependency check is performed before the server instance is booted. Thus,
|
|
122
125
|
it cannot occur during runtime.
|
package/docs/Ecosystem.md
CHANGED
|
@@ -44,6 +44,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
44
44
|
- [`fastify-routes`](https://github.com/fastify/fastify-routes) Plugin that provides a `Map` of routes.
|
|
45
45
|
- [`fastify-schedule`](https://github.com/fastify/fastify-schedule) Plugin for scheduling periodic jobs, based on [toad-scheduler](https://github.com/kibertoad/toad-scheduler).
|
|
46
46
|
- [`fastify-sensible`](https://github.com/fastify/fastify-sensible) Defaults for Fastify that everyone can agree on. It adds some useful decorators such as HTTP errors and assertions, but also more request and reply methods.
|
|
47
|
+
- [`@fastify/session`](https://github.com/fastify/session) a session plugin for Fastify.
|
|
47
48
|
- [`fastify-static`](https://github.com/fastify/fastify-static) Plugin for serving static files as fast as possible.
|
|
48
49
|
- [`fastify-swagger`](https://github.com/fastify/fastify-swagger) Plugin for serving Swagger/OpenAPI documentation for Fastify, supporting dynamic generation.
|
|
49
50
|
- [`fastify-websocket`](https://github.com/fastify/fastify-websocket) WebSocket support for Fastify. Built upon [websocket-stream](https://github.com/maxogden/websocket-stream).
|
|
@@ -69,6 +70,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
69
70
|
- [`arecibo`](https://github.com/nucleode/arecibo) Fastify ping responder for Kubernetes Liveness and Readiness Probes.
|
|
70
71
|
- [`cls-rtracer`](https://github.com/puzpuzpuz/cls-rtracer) Fastify middleware for CLS-based request ID generation. An out-of-the-box solution for adding request IDs into your logs.
|
|
71
72
|
- [`fastify-405`](https://github.com/Eomm/fastify-405) Fastify plugin that adds 405 HTTP status to your routes
|
|
73
|
+
- [`fastify-allow`](https://github.com/mattbishop/fastify-allow) Fastify plugin that automatically adds an Allow header to responses with routes. Also sends 405 responses for routes that have a handler but not for the request's method.
|
|
72
74
|
- [`fastify-amqp`](https://github.com/RafaelGSS/fastify-amqp) Fastify AMQP connection plugin, to use with RabbitMQ or another connector. Just a wrapper to [`amqplib`](https://github.com/squaremo/amqp.node).
|
|
73
75
|
- [`fastify-angular-universal`](https://github.com/exequiel09/fastify-angular-universal) Angular server-side rendering support using [`@angular/platform-server`](https://github.com/angular/angular/tree/master/packages/platform-server) for Fastify
|
|
74
76
|
- [`fastify-api-key`](https://github.com/arkerone/fastify-api-key) Fastify plugin to authenticate HTTP requests based on api key and signature
|
|
@@ -162,6 +164,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
162
164
|
- [`fastify-qs`](https://github.com/webdevium/fastify-qs) A plugin for Fastify that adds support for parsing URL query parameters with [qs](https://github.com/ljharb/qs).
|
|
163
165
|
- [`fastify-raw-body`](https://github.com/Eomm/fastify-raw-body) Add the `request.rawBody` field.
|
|
164
166
|
- [`fastify-rbac`](https://gitlab.com/m03geek/fastify-rbac) Fastify role-based access control plugin.
|
|
167
|
+
- [`fastify-recaptcha`](https://github.com/qwertyforce/fastify-recaptcha) Fastify plugin for recaptcha verification.
|
|
165
168
|
- [`fastify-redis-channels`](https://github.com/hearit-io/fastify-redis-channels) A plugin for fast, reliable, and scalable channels implementation based on Redis streams.
|
|
166
169
|
- [`fastify-register-routes`](https://github.com/israeleriston/fastify-register-routes) Plugin to automatically load routes from a specified path and optionally limit loaded file names by a regular expression.
|
|
167
170
|
- [`fastify-response-time`](https://github.com/lolo32/fastify-response-time) Add `X-Response-Time` header at each request for Fastify, in milliseconds.
|
|
@@ -176,7 +179,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
176
179
|
- [`fastify-sentry`](https://github.com/alex-ppg/fastify-sentry) Fastify plugin to add the Sentry SDK error handler to requests.
|
|
177
180
|
- [`fastify-sequelize`](https://github.com/lyquocnam/fastify-sequelize) Fastify plugin work with Sequelize (adapter for NodeJS -> Sqlite, Mysql, Mssql, Postgres).
|
|
178
181
|
- [`fastify-server-session`](https://github.com/jsumners/fastify-server-session) A session plugin with support for arbitrary backing caches via `fastify-caching`.
|
|
179
|
-
- [`fastify-
|
|
182
|
+
- [`fastify-slonik`](https://github.com/Unbuttun/fastify-slonik) Fastify Slonik plugin, with this you can use slonik in every part of your server.
|
|
180
183
|
- [`fastify-soap-client`](https://github.com/fastify/fastify-soap-client) a SOAP client plugin for Fastify.
|
|
181
184
|
- [`fastify-socket.io`](https://github.com/alemagio/fastify-socket.io) a Socket.io plugin for Fastify.
|
|
182
185
|
- [`fastify-sse`](https://github.com/lolo32/fastify-sse) to provide Server-Sent Events with `reply.sse( … )` to Fastify.
|
|
@@ -202,3 +205,4 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
202
205
|
- [`nstats`](https://github.com/Phara0h/nstats) A fast and compact way to get all your network and process stats for your node application. Websocket, HTTP/S, and prometheus compatible!
|
|
203
206
|
- [`oas-fastify`](https://github.com/ahmadnassri/node-oas-fastify) OAS 3.x to Fastify routes automation. Automatically generates route handlers with fastify configuration and validation.
|
|
204
207
|
- [`openapi-validator-middleware`](https://github.com/PayU/openapi-validator-middleware#fastify) Swagger and OpenAPI 3.0 spec-based request validation middleware that supports Fastify.
|
|
208
|
+
- [`sequelize-fastify`](https://github.com/hsynlms/sequelize-fastify) A simple and lightweight Sequelize plugin for Fastify.
|
package/docs/Getting-Started.md
CHANGED
|
@@ -184,7 +184,7 @@ async function routes (fastify, options) {
|
|
|
184
184
|
|
|
185
185
|
fastify.get('/animals/:animal', async (request, reply) => {
|
|
186
186
|
const result = await collection.findOne({ animal: request.params.animal })
|
|
187
|
-
if (result
|
|
187
|
+
if (!result) {
|
|
188
188
|
throw new Error('Invalid value')
|
|
189
189
|
}
|
|
190
190
|
return result
|
|
@@ -200,7 +200,7 @@ As you can see, we used `register` for both the database connector and the regis
|
|
|
200
200
|
This is one of the best features of Fastify, it will load your plugins in the same order you declare them, and it will load the next plugin only once the current one has been loaded. In this way, we can register the database connector in the first plugin and use it in the second *(read [here](Plugins.md#handle-the-scope) to understand how to handle the scope of a plugin)*.
|
|
201
201
|
Plugin loading starts when you call `fastify.listen()`, `fastify.inject()` or `fastify.ready()`
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
The MongoDB plugin uses the `decorate` API to add custom objects to the Fastify instance, making them available for use everywhere. Use of this API is encouraged to facilitate easy code reuse and to decrease code or logic duplication.
|
|
204
204
|
|
|
205
205
|
To dig deeper into how Fastify plugins work, how to develop new plugins, and for details on how to use the whole Fastify API to deal with the complexity of asynchronously bootstrapping an application, read [the hitchhiker's guide to plugins](Plugins-Guide.md).
|
|
206
206
|
|
package/docs/Reply.md
CHANGED
|
@@ -53,10 +53,11 @@ and properties:
|
|
|
53
53
|
- `.serializer(function)` - Sets a custom serializer for the payload.
|
|
54
54
|
- `.send(payload)` - Sends the payload to the user, could be a plain text, a buffer, JSON, stream, or an Error object.
|
|
55
55
|
- `.sent` - A boolean value that you can use if you need to know if `send` has already been called.
|
|
56
|
-
- `.raw` - The [`http.ServerResponse`](https://nodejs.org/dist/latest/docs/api/http.html#http_class_http_serverresponse) from Node core.
|
|
57
|
-
- `.res` *(deprecated, use `.raw` instead)* - The [`http.ServerResponse`](https://nodejs.org/dist/latest/docs/api/http.html#http_class_http_serverresponse) from Node core.
|
|
56
|
+
- `.raw` - The [`http.ServerResponse`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_class_http_serverresponse) from Node core.
|
|
57
|
+
- `.res` *(deprecated, use `.raw` instead)* - The [`http.ServerResponse`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_class_http_serverresponse) from Node core.
|
|
58
58
|
- `.log` - The logger instance of the incoming request.
|
|
59
59
|
- `.request` - The incoming request.
|
|
60
|
+
- `.context` - Access the [Request's context](Request.md#Request) property.
|
|
60
61
|
|
|
61
62
|
```js
|
|
62
63
|
fastify.get('/', options, function (request, reply) {
|
|
@@ -108,7 +109,7 @@ fastify.get('/', async function (req, rep) {
|
|
|
108
109
|
Sets a response header. If the value is omitted or undefined, it is coerced
|
|
109
110
|
to `''`.
|
|
110
111
|
|
|
111
|
-
For more information, see [`http.ServerResponse#setHeader`](https://nodejs.org/dist/latest/docs/api/http.html#http_response_setheader_name_value).
|
|
112
|
+
For more information, see [`http.ServerResponse#setHeader`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_response_setheader_name_value).
|
|
112
113
|
|
|
113
114
|
<a name="headers"></a>
|
|
114
115
|
### .headers(object)
|
|
@@ -227,7 +228,7 @@ See [`.send()`](#send) for more information on sending different types of values
|
|
|
227
228
|
|
|
228
229
|
<a name="raw"></a>
|
|
229
230
|
### .raw
|
|
230
|
-
This is the [`http.ServerResponse`](https://nodejs.org/dist/latest/docs/api/http.html#http_class_http_serverresponse) from Node core. Whilst you are using the Fastify `Reply` object, the use of `Reply.raw` functions is at your own risk as you are skipping all the Fastify
|
|
231
|
+
This is the [`http.ServerResponse`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_class_http_serverresponse) from Node core. Whilst you are using the Fastify `Reply` object, the use of `Reply.raw` functions is at your own risk as you are skipping all the Fastify
|
|
231
232
|
logic of handling the HTTP response. e.g.:
|
|
232
233
|
|
|
233
234
|
```js
|
|
@@ -300,7 +301,7 @@ fastify.get('/json', options, function (request, reply) {
|
|
|
300
301
|
|
|
301
302
|
<a name="send-streams"></a>
|
|
302
303
|
#### Streams
|
|
303
|
-
*send* can also handle streams out of the box
|
|
304
|
+
*send* can also handle streams out of the box. If you are sending a stream and you have not set a `'Content-Type'` header, *send* will set it at `'application/octet-stream'`.
|
|
304
305
|
```js
|
|
305
306
|
fastify.get('/streams', function (request, reply) {
|
|
306
307
|
const fs = require('fs')
|
package/docs/Request.md
CHANGED
|
@@ -6,7 +6,7 @@ Request is a core Fastify object containing the following fields:
|
|
|
6
6
|
- `query` - the parsed querystring
|
|
7
7
|
- `body` - the body
|
|
8
8
|
- `params` - the params matching the URL
|
|
9
|
-
- `headers` - the headers
|
|
9
|
+
- [`headers`](#headers) - the headers getter and setter
|
|
10
10
|
- `raw` - the incoming HTTP request from Node core
|
|
11
11
|
- `req` *(deprecated, use `.raw` instead)* - the incoming HTTP request from Node core
|
|
12
12
|
- `server` - The Fastify server instance, scoped to the current [encapsulation context](Encapsulation.md)
|
|
@@ -23,7 +23,23 @@ Request is a core Fastify object containing the following fields:
|
|
|
23
23
|
- `is404` - true if request is being handled by 404 handler, false if it is not
|
|
24
24
|
- `connection` - Deprecated, use `socket` instead. The underlying connection of the incoming request.
|
|
25
25
|
- `socket` - the underlying connection of the incoming request
|
|
26
|
+
- `context` - A Fastify internal object. You should not use it directly or modify it. It is usefull to access one special key:
|
|
27
|
+
- `context.config` - The route [`config`](Routes.md#routes-config) object.
|
|
26
28
|
|
|
29
|
+
### Headers
|
|
30
|
+
|
|
31
|
+
The `request.headers` is a getter that return an Object with the headers of the incoming request.
|
|
32
|
+
You can set custom headers like this:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
request.headers = {
|
|
36
|
+
'foo': 'bar',
|
|
37
|
+
'baz': 'qux'
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This operation will add to the request headers the new values that can be read calling `request.headers.bar`.
|
|
42
|
+
Moreover, you can still access the standard request's headers with the `request.raw.headers` property.
|
|
27
43
|
|
|
28
44
|
```js
|
|
29
45
|
fastify.post('/:params', options, function (request, reply) {
|
|
@@ -38,6 +54,9 @@ fastify.post('/:params', options, function (request, reply) {
|
|
|
38
54
|
console.log(request.ips)
|
|
39
55
|
console.log(request.hostname)
|
|
40
56
|
console.log(request.protocol)
|
|
57
|
+
console.log(request.url)
|
|
58
|
+
console.log(request.routerMethod)
|
|
59
|
+
console.log(request.routerPath)
|
|
41
60
|
request.log.info('some info')
|
|
42
61
|
})
|
|
43
62
|
```
|
package/docs/Routes.md
CHANGED
|
@@ -427,7 +427,7 @@ Fastify will require a request `Accept-Version` header to be set if the route ha
|
|
|
427
427
|
fastify.route({
|
|
428
428
|
method: 'GET',
|
|
429
429
|
url: '/',
|
|
430
|
-
|
|
430
|
+
constraints: { version: '1.2.0' },
|
|
431
431
|
handler: function (request, reply) {
|
|
432
432
|
reply.send({ hello: 'world' })
|
|
433
433
|
}
|
|
@@ -475,7 +475,7 @@ You can provide a `host` key in the `constraints` route option for to limit that
|
|
|
475
475
|
fastify.route({
|
|
476
476
|
method: 'GET',
|
|
477
477
|
url: '/',
|
|
478
|
-
|
|
478
|
+
constraints: { host: 'auth.fastify.io' },
|
|
479
479
|
handler: function (request, reply) {
|
|
480
480
|
reply.send('hello world from auth.fastify.io')
|
|
481
481
|
}
|
|
@@ -508,7 +508,7 @@ RegExp `host` constraints can also be specified allowing constraining to hosts m
|
|
|
508
508
|
fastify.route({
|
|
509
509
|
method: 'GET',
|
|
510
510
|
url: '/',
|
|
511
|
-
|
|
511
|
+
constraints: { host: /.*\.fastify\.io/ }, // will match any subdomain of fastify.io
|
|
512
512
|
handler: function (request, reply) {
|
|
513
513
|
reply.send('hello world from ' + request.headers.host)
|
|
514
514
|
}
|
package/docs/Server.md
CHANGED
|
@@ -11,7 +11,7 @@ document describes the properties available in that options object.
|
|
|
11
11
|
<a name="factory-http2"></a>
|
|
12
12
|
### `http2`
|
|
13
13
|
|
|
14
|
-
If `true` Node.js core's [HTTP/2](https://nodejs.org/dist/latest-
|
|
14
|
+
If `true` Node.js core's [HTTP/2](https://nodejs.org/dist/latest-v14.x/docs/api/http2.html) module is used for binding the socket.
|
|
15
15
|
|
|
16
16
|
+ Default: `false`
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@ If `true` Node.js core's [HTTP/2](https://nodejs.org/dist/latest-v8.x/docs/api/h
|
|
|
20
20
|
|
|
21
21
|
An object used to configure the server's listening socket for TLS. The options
|
|
22
22
|
are the same as the Node.js core
|
|
23
|
-
[`createServer` method](https://nodejs.org/dist/latest-
|
|
23
|
+
[`createServer` method](https://nodejs.org/dist/latest-v14.x/docs/api/https.html#https_https_createserver_options_requestlistener).
|
|
24
24
|
When this property is `null`, the socket will not be configured for TLS.
|
|
25
25
|
|
|
26
26
|
This option also applies when the
|
|
@@ -113,7 +113,7 @@ for more details about prototype poisoning attacks.
|
|
|
113
113
|
|
|
114
114
|
Possible values are `'error'`, `'remove'` and `'ignore'`.
|
|
115
115
|
|
|
116
|
-
+ Default: `'
|
|
116
|
+
+ Default: `'error'`
|
|
117
117
|
|
|
118
118
|
<a name="factory-logger"></a>
|
|
119
119
|
### `logger`
|
|
@@ -454,8 +454,10 @@ const fastify = require('fastify')({
|
|
|
454
454
|
Set a default
|
|
455
455
|
[timeout](https://nodejs.org/api/http2.html#http2_http2session_settimeout_msecs_callback) to every incoming HTTP/2 session. The session will be closed on the timeout. Default: `5000` ms.
|
|
456
456
|
|
|
457
|
-
Note that this is needed to offer the graceful "close" experience when
|
|
458
|
-
|
|
457
|
+
Note that this is needed to offer the graceful "close" experience when using HTTP/2.
|
|
458
|
+
The low default has been chosen to mitigate denial of service attacks.
|
|
459
|
+
When the server is behind a load balancer or can scale automatically this value can be
|
|
460
|
+
increased to fit the use case. Node core defaults this to `0`. `
|
|
459
461
|
|
|
460
462
|
<a name="framework-errors"></a>
|
|
461
463
|
### `frameworkErrors`
|
package/docs/TypeScript.md
CHANGED
|
@@ -85,7 +85,7 @@ The type system heavily relies on generic properties to provide the most accurat
|
|
|
85
85
|
'h-Custom': string;
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
|
-
3. Using the two interfaces, define a new API route and pass them as generics. The shorthand route methods (i.e. `.get`) accept a generic object `
|
|
88
|
+
3. Using the two interfaces, define a new API route and pass them as generics. The shorthand route methods (i.e. `.get`) accept a generic object `RouteGenericInterface` containing five named properties: `Body`, `Querystring`, `Params`, `Headers` and `Reply`. The interfaces `Body`, `Querystring`, `Params` and `Headers` will be passed down through the route method into the route method handler `request` instance and the `Reply` interface to the `reply` instance.
|
|
89
89
|
```typescript
|
|
90
90
|
server.get<{
|
|
91
91
|
Querystring: IQuerystring,
|
|
@@ -164,7 +164,7 @@ When you want to use it for validation of some payload in a fastify route you ca
|
|
|
164
164
|
```typescript
|
|
165
165
|
const app = fastify();
|
|
166
166
|
|
|
167
|
-
app.post<{ Body: UserType;
|
|
167
|
+
app.post<{ Body: UserType; Reply: UserType }>(
|
|
168
168
|
"/",
|
|
169
169
|
{
|
|
170
170
|
schema: {
|
|
@@ -599,7 +599,7 @@ The Fastify API is powered by the `fastify()` method. In JavaScript you would im
|
|
|
599
599
|
const f = fastify()
|
|
600
600
|
f.listen(8080, () => { console.log('running') })
|
|
601
601
|
```
|
|
602
|
-
- Destructuring is
|
|
602
|
+
- Destructuring is supported and will resolve types properly
|
|
603
603
|
```typescript
|
|
604
604
|
const { fastify } = require('fastify')
|
|
605
605
|
|
package/fastify.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { FastifyReply } from './types/reply'
|
|
|
14
14
|
import { FastifySchemaValidationError } from './types/schema'
|
|
15
15
|
import { ConstructorAction, ProtoAction } from "./types/content-type-parser";
|
|
16
16
|
import { Socket } from 'net'
|
|
17
|
+
import { Options as FJSOptions } from 'fast-json-stringify'
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Fastify factory function for the standard fastify http, https, or http2 server instance.
|
|
@@ -102,6 +103,7 @@ export type FastifyServerOptions<
|
|
|
102
103
|
onProtoPoisoning?: ProtoAction,
|
|
103
104
|
onConstructorPoisoning?: ConstructorAction,
|
|
104
105
|
logger?: boolean | FastifyLoggerOptions<RawServer> | Logger,
|
|
106
|
+
serializerOpts?: FJSOptions | Record<string, unknown>,
|
|
105
107
|
serverFactory?: FastifyServerFactory<RawServer>,
|
|
106
108
|
caseSensitive?: boolean,
|
|
107
109
|
requestIdHeader?: string,
|
|
@@ -122,7 +124,7 @@ export type FastifyServerOptions<
|
|
|
122
124
|
deriveVersion<Context>(req: Object, ctx?: Context): string // not a fan of using Object here. Also what is Context? Can either of these be better defined?
|
|
123
125
|
},
|
|
124
126
|
constraints?: {
|
|
125
|
-
[name: string]: ConstraintStrategy<FindMyWayVersion<RawServer
|
|
127
|
+
[name: string]: ConstraintStrategy<FindMyWayVersion<RawServer>, unknown>,
|
|
126
128
|
},
|
|
127
129
|
return503OnClosing?: boolean,
|
|
128
130
|
ajv?: {
|
|
@@ -163,7 +165,7 @@ export type { Chain as LightMyRequestChain, InjectOptions, Response as LightMyRe
|
|
|
163
165
|
export { FastifyRequest, RequestGenericInterface } from './types/request'
|
|
164
166
|
export { FastifyReply } from './types/reply'
|
|
165
167
|
export { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin } from './types/plugin'
|
|
166
|
-
export { FastifyInstance } from './types/instance'
|
|
168
|
+
export { FastifyInstance, PrintRoutesOptions } from './types/instance'
|
|
167
169
|
export { FastifyLoggerOptions, FastifyLoggerInstance, FastifyLogFn, LogLevel } from './types/logger'
|
|
168
170
|
export { FastifyContext, FastifyContextConfig } from './types/context'
|
|
169
171
|
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler } from './types/route'
|
package/fastify.js
CHANGED
|
@@ -4,8 +4,9 @@ const Avvio = require('avvio')
|
|
|
4
4
|
const http = require('http')
|
|
5
5
|
const querystring = require('querystring')
|
|
6
6
|
let lightMyRequest
|
|
7
|
+
let version
|
|
8
|
+
let versionLoaded = false
|
|
7
9
|
|
|
8
|
-
const { version } = require('./package.json')
|
|
9
10
|
const {
|
|
10
11
|
kAvvioBoot,
|
|
11
12
|
kChildren,
|
|
@@ -271,6 +272,8 @@ function fastify (options) {
|
|
|
271
272
|
hasContentTypeParser: ContentTypeParser.helpers.hasContentTypeParser,
|
|
272
273
|
getDefaultJsonParser: ContentTypeParser.defaultParsers.getDefaultJsonParser,
|
|
273
274
|
defaultTextParser: ContentTypeParser.defaultParsers.defaultTextParser,
|
|
275
|
+
removeContentTypeParser: ContentTypeParser.helpers.removeContentTypeParser,
|
|
276
|
+
removeAllContentTypeParsers: ContentTypeParser.helpers.removeAllContentTypeParsers,
|
|
274
277
|
// Fastify architecture methods (initialized by Avvio)
|
|
275
278
|
register: null,
|
|
276
279
|
after: null,
|
|
@@ -322,6 +325,9 @@ function fastify (options) {
|
|
|
322
325
|
},
|
|
323
326
|
version: {
|
|
324
327
|
get () {
|
|
328
|
+
if (versionLoaded === false) {
|
|
329
|
+
version = loadVersion()
|
|
330
|
+
}
|
|
325
331
|
return version
|
|
326
332
|
}
|
|
327
333
|
},
|
|
@@ -535,9 +541,8 @@ function fastify (options) {
|
|
|
535
541
|
|
|
536
542
|
function defaultClientErrorHandler (err, socket) {
|
|
537
543
|
// In case of a connection reset, the socket has been destroyed and there is nothing that needs to be done.
|
|
538
|
-
// https://
|
|
539
|
-
|
|
540
|
-
if (err.code === 'ECONNRESET') {
|
|
544
|
+
// https://nodejs.org/api/http.html#http_event_clienterror
|
|
545
|
+
if (err.code === 'ECONNRESET' || socket.destroyed) {
|
|
541
546
|
return
|
|
542
547
|
}
|
|
543
548
|
|
|
@@ -551,11 +556,14 @@ function fastify (options) {
|
|
|
551
556
|
// In the vast majority of cases, it's a network error and/or some
|
|
552
557
|
// config issue on the load balancer side.
|
|
553
558
|
this.log.trace({ err }, 'client error')
|
|
559
|
+
// Copying standard node behaviour
|
|
560
|
+
// https://github.com/nodejs/node/blob/6ca23d7846cb47e84fd344543e394e50938540be/lib/_http_server.js#L666
|
|
554
561
|
|
|
555
562
|
// If the socket is not writable, there is no reason to try to send data.
|
|
556
|
-
if (socket.writable) {
|
|
557
|
-
socket.
|
|
563
|
+
if (socket.writable && socket.bytesWritten === 0) {
|
|
564
|
+
socket.write(`HTTP/1.1 400 Bad Request\r\nContent-Length: ${body.length}\r\nContent-Type: application/json\r\n\r\n${body}`)
|
|
558
565
|
}
|
|
566
|
+
socket.destroy(err)
|
|
559
567
|
}
|
|
560
568
|
|
|
561
569
|
// If the router does not match any route, every request will land here
|
|
@@ -671,6 +679,20 @@ function wrapRouting (httpHandler, { rewriteUrl, logger }) {
|
|
|
671
679
|
}
|
|
672
680
|
}
|
|
673
681
|
|
|
682
|
+
function loadVersion () {
|
|
683
|
+
versionLoaded = true
|
|
684
|
+
const fs = require('fs')
|
|
685
|
+
const path = require('path')
|
|
686
|
+
try {
|
|
687
|
+
const pkgPath = path.join(__dirname, 'package.json')
|
|
688
|
+
fs.accessSync(pkgPath, fs.constants.R_OK)
|
|
689
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath))
|
|
690
|
+
return pkg.name === 'fastify' ? pkg.version : undefined
|
|
691
|
+
} catch (e) {
|
|
692
|
+
return undefined
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
674
696
|
/**
|
|
675
697
|
* These export configurations enable JS and TS developers
|
|
676
698
|
* to consumer fastify in whatever way best suits their needs.
|
package/lib/contentTypeParser.js
CHANGED
|
@@ -116,6 +116,27 @@ ContentTypeParser.prototype.getParser = function (contentType) {
|
|
|
116
116
|
return this.customParsers['']
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
ContentTypeParser.prototype.removeAll = function () {
|
|
120
|
+
this.customParsers = {}
|
|
121
|
+
this.parserRegExpList = []
|
|
122
|
+
this.parserList = []
|
|
123
|
+
this.cache = lru(100)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
ContentTypeParser.prototype.remove = function (contentType) {
|
|
127
|
+
if (!(typeof contentType === 'string' || contentType instanceof RegExp)) throw new FST_ERR_CTP_INVALID_TYPE()
|
|
128
|
+
|
|
129
|
+
delete this.customParsers[contentType]
|
|
130
|
+
|
|
131
|
+
const parsers = typeof contentType === 'string' ? this.parserList : this.parserRegExpList
|
|
132
|
+
|
|
133
|
+
const idx = parsers.findIndex(ct => ct.toString() === contentType.toString())
|
|
134
|
+
|
|
135
|
+
if (idx > -1) {
|
|
136
|
+
parsers.splice(idx, 1)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
119
140
|
ContentTypeParser.prototype.run = function (contentType, handler, request, reply) {
|
|
120
141
|
const parser = this.cache.get(contentType) || this.getParser(contentType)
|
|
121
142
|
|
|
@@ -297,11 +318,35 @@ function hasContentTypeParser (contentType) {
|
|
|
297
318
|
return this[kContentTypeParser].hasParser(contentType)
|
|
298
319
|
}
|
|
299
320
|
|
|
321
|
+
function removeContentTypeParser (contentType) {
|
|
322
|
+
if (this[kState].started) {
|
|
323
|
+
throw new Error('Cannot call "removeContentTypeParser" when fastify instance is already started!')
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (Array.isArray(contentType)) {
|
|
327
|
+
for (const type of contentType) {
|
|
328
|
+
this[kContentTypeParser].remove(type)
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
this[kContentTypeParser].remove(contentType)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function removeAllContentTypeParsers () {
|
|
336
|
+
if (this[kState].started) {
|
|
337
|
+
throw new Error('Cannot call "removeAllContentTypeParsers" when fastify instance is already started!')
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
this[kContentTypeParser].removeAll()
|
|
341
|
+
}
|
|
342
|
+
|
|
300
343
|
module.exports = ContentTypeParser
|
|
301
344
|
module.exports.helpers = {
|
|
302
345
|
buildContentTypeParser,
|
|
303
346
|
addContentTypeParser,
|
|
304
|
-
hasContentTypeParser
|
|
347
|
+
hasContentTypeParser,
|
|
348
|
+
removeContentTypeParser,
|
|
349
|
+
removeAllContentTypeParsers
|
|
305
350
|
}
|
|
306
351
|
module.exports.defaultParsers = {
|
|
307
352
|
getDefaultJsonParser,
|
package/lib/logger.js
CHANGED
|
@@ -35,7 +35,7 @@ function createPinoLogger (opts, stream) {
|
|
|
35
35
|
if (prevLogger[serializersSym]) {
|
|
36
36
|
opts.serializers = Object.assign({}, opts.serializers, prevLogger[serializersSym])
|
|
37
37
|
}
|
|
38
|
-
logger = prevLogger.child(opts)
|
|
38
|
+
logger = prevLogger.child({}, opts)
|
|
39
39
|
opts.logger = prevLogger
|
|
40
40
|
opts.genReqId = prevGenReqId
|
|
41
41
|
} else {
|
package/lib/pluginUtils.js
CHANGED
|
@@ -109,7 +109,9 @@ function registerPluginName (fn) {
|
|
|
109
109
|
|
|
110
110
|
function registerPlugin (fn) {
|
|
111
111
|
registerPluginName.call(this, fn)
|
|
112
|
-
|
|
112
|
+
if (this.version !== undefined) {
|
|
113
|
+
checkVersion.call(this, fn)
|
|
114
|
+
}
|
|
113
115
|
checkDecorators.call(this, fn)
|
|
114
116
|
checkDependencies.call(this, fn)
|
|
115
117
|
return shouldSkipOverride(fn)
|
package/lib/reply.js
CHANGED
|
@@ -548,8 +548,12 @@ function handleError (reply, error, cb) {
|
|
|
548
548
|
reply[kReplyErrorHandlerCalled] = true
|
|
549
549
|
reply[kReplyHeaders]['content-length'] = undefined
|
|
550
550
|
const result = errorHandler(error, reply.request, reply)
|
|
551
|
-
if (result
|
|
552
|
-
|
|
551
|
+
if (result !== undefined) {
|
|
552
|
+
if (result !== null && typeof result.then === 'function') {
|
|
553
|
+
wrapThenable(result, reply)
|
|
554
|
+
} else {
|
|
555
|
+
reply.send(result)
|
|
556
|
+
}
|
|
553
557
|
}
|
|
554
558
|
return
|
|
555
559
|
}
|
package/lib/request.js
CHANGED
|
@@ -162,7 +162,13 @@ Object.defineProperties(Request.prototype, {
|
|
|
162
162
|
},
|
|
163
163
|
headers: {
|
|
164
164
|
get () {
|
|
165
|
+
if (this.additionalHeaders) {
|
|
166
|
+
return Object.assign({}, this.raw.headers, this.additionalHeaders)
|
|
167
|
+
}
|
|
165
168
|
return this.raw.headers
|
|
169
|
+
},
|
|
170
|
+
set (headers) {
|
|
171
|
+
this.additionalHeaders = headers
|
|
166
172
|
}
|
|
167
173
|
},
|
|
168
174
|
server: {
|
package/lib/route.js
CHANGED
|
@@ -247,7 +247,7 @@ function buildRouting (options) {
|
|
|
247
247
|
opts.schemaErrorFormatter || this[kSchemaErrorFormatter]
|
|
248
248
|
)
|
|
249
249
|
|
|
250
|
-
const headRouteExists = router.find('HEAD',
|
|
250
|
+
const headRouteExists = router.find('HEAD', url) != null
|
|
251
251
|
|
|
252
252
|
try {
|
|
253
253
|
router.on(opts.method, opts.url, { constraints }, routeHandler, context)
|
|
@@ -345,15 +345,18 @@ function buildRouting (options) {
|
|
|
345
345
|
|
|
346
346
|
const id = req.headers[requestIdHeader] || genReqId(req)
|
|
347
347
|
|
|
348
|
+
const loggerBinding = {
|
|
349
|
+
[requestIdLogLabel]: id
|
|
350
|
+
}
|
|
351
|
+
|
|
348
352
|
const loggerOpts = {
|
|
349
|
-
[requestIdLogLabel]: id,
|
|
350
353
|
level: context.logLevel
|
|
351
354
|
}
|
|
352
355
|
|
|
353
356
|
if (context.logSerializers) {
|
|
354
357
|
loggerOpts.serializers = context.logSerializers
|
|
355
358
|
}
|
|
356
|
-
const childLogger = logger.child(loggerOpts)
|
|
359
|
+
const childLogger = logger.child(loggerBinding, loggerOpts)
|
|
357
360
|
childLogger[kDisableRequestLogging] = disableRequestLogging
|
|
358
361
|
|
|
359
362
|
const queryPrefix = req.url.indexOf('?')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.20.2",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
"tap": "^15.0.5",
|
|
165
165
|
"tap-mocha-reporter": "^5.0.1",
|
|
166
166
|
"then-sleep": "^1.0.1",
|
|
167
|
-
"tsd": "^0.
|
|
167
|
+
"tsd": "^0.17.0",
|
|
168
168
|
"typescript": "^4.0.2",
|
|
169
169
|
"undici": "^3.3.5",
|
|
170
170
|
"x-xss-protection": "^2.0.0",
|
|
@@ -177,10 +177,10 @@
|
|
|
177
177
|
"fast-json-stringify": "^2.5.2",
|
|
178
178
|
"fastify-error": "^0.3.0",
|
|
179
179
|
"fastify-warning": "^0.2.0",
|
|
180
|
-
"find-my-way": "^4.
|
|
180
|
+
"find-my-way": "^4.1.0",
|
|
181
181
|
"flatstr": "^1.0.12",
|
|
182
182
|
"light-my-request": "^4.2.0",
|
|
183
|
-
"pino": "^6.
|
|
183
|
+
"pino": "^6.13.0",
|
|
184
184
|
"proxy-addr": "^2.0.7",
|
|
185
185
|
"readable-stream": "^3.4.0",
|
|
186
186
|
"rfdc": "^1.1.4",
|