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.
@@ -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
- You can also use the `hasContentTypeParser` API to find if a specific content type parser already exists.
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
+ ```
@@ -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-session`](https://github.com/SerayaEryn/fastify-session) a session plugin for 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.
@@ -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 === null) {
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
- We have also used the `decorate` API to add custom objects to the Fastify namespace, making them available for use everywhere. Use of this API is encouraged to facilitate easy code reuse and to decrease code or logic duplication.
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, internally uses [pump](https://www.npmjs.com/package/pump) to avoid leaks of file descriptors. If you are sending a stream and you have not set a `'Content-Type'` header, *send* will set it at `'application/octet-stream'`.
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
- { constraints: { version: '1.2.0'} },
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
- { constraints: { host: 'auth.fastify.io' } },
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
- { constraints: { host: /.*\.fastify\.io/ } }, // will match any subdomain of fastify.io
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-v8.x/docs/api/http2.html) module is used for binding the socket.
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-v8.x/docs/api/https.html#https_https_createserver_options_requestlistener).
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: `'ignore'`
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
- using HTTP/2. Node core defaults this to `0`.
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`
@@ -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 `RequestGenericInterface` containing four named properties: `Body`, `Querystring`, `Params`, and `Headers`. The interfaces will be passed down through the route method into the route method handler `request` instance.
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; Response: 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 still supported, but will also not resolve types
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://github.com/fastify/fastify/issues/2036
539
- // https://github.com/nodejs/node/issues/33302
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.end(`HTTP/1.1 400 Bad Request\r\nContent-Length: ${body.length}\r\nContent-Type: application/json\r\n\r\n${body}`)
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.
@@ -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 {
@@ -109,7 +109,9 @@ function registerPluginName (fn) {
109
109
 
110
110
  function registerPlugin (fn) {
111
111
  registerPluginName.call(this, fn)
112
- checkVersion.call(this, fn)
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 && typeof result.then === 'function') {
552
- wrapThenable(result, reply)
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', path) != null
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.19.1",
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.14.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.0.0",
180
+ "find-my-way": "^4.1.0",
181
181
  "flatstr": "^1.0.12",
182
182
  "light-my-request": "^4.2.0",
183
- "pino": "^6.2.1",
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",