fastify 4.19.2 → 4.20.0
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/.c8rc.json +8 -0
- package/.taprc +3 -2
- package/SECURITY.md +9 -0
- package/docs/Guides/Prototype-Poisoning.md +2 -2
- package/docs/Reference/Errors.md +39 -17
- package/docs/Reference/Logging.md +1 -1
- package/docs/Reference/Plugins.md +4 -0
- package/docs/Reference/Routes.md +8 -0
- package/docs/Reference/Server.md +38 -0
- package/fastify.d.ts +3 -2
- package/fastify.js +36 -17
- package/lib/context.js +6 -0
- package/lib/errors.js +50 -19
- package/lib/fourOhFour.js +5 -9
- package/lib/handleRequest.js +3 -5
- package/lib/hooks.js +91 -25
- package/lib/logger.js +40 -3
- package/lib/reply.js +3 -9
- package/lib/reqIdGenFactory.js +18 -3
- package/lib/route.js +14 -61
- package/lib/schema-controller.js +2 -0
- package/lib/server.js +23 -8
- package/lib/symbols.js +1 -0
- package/package.json +8 -7
- package/test/500s.test.js +22 -0
- package/test/childLoggerFactory.test.js +91 -0
- package/test/encapsulated-child-logger-factory.test.js +69 -0
- package/test/fastify-instance.test.js +43 -10
- package/test/inject.test.js +1 -2
- package/test/internals/errors.test.js +843 -0
- package/test/internals/hookRunner.test.js +22 -8
- package/test/internals/initialConfig.test.js +9 -2
- package/test/internals/reply.test.js +49 -43
- package/test/internals/reqIdGenFactory.test.js +129 -0
- package/test/internals/request-validate.test.js +40 -1
- package/test/internals/request.test.js +14 -4
- package/test/reply-error.test.js +25 -0
- package/test/request-id.test.js +131 -0
- package/test/route.test.js +135 -0
- package/test/server.test.js +64 -2
- package/test/types/errors.test-d.ts +82 -0
- package/test/types/fastify.test-d.ts +4 -0
- package/test/types/instance.test-d.ts +37 -0
- package/test/types/reply.test-d.ts +1 -0
- package/test/types/route.test-d.ts +3 -0
- package/types/errors.d.ts +29 -23
- package/types/instance.d.ts +33 -7
- package/types/logger.d.ts +25 -0
- package/types/reply.d.ts +1 -1
- package/types/route.d.ts +2 -1
package/.c8rc.json
ADDED
package/.taprc
CHANGED
package/SECURITY.md
CHANGED
|
@@ -27,6 +27,15 @@ reported vulnerabilities:
|
|
|
27
27
|
validity of the report. In any case, the report should follow the same process
|
|
28
28
|
as outlined below of inviting the maintainers to review and accept the
|
|
29
29
|
vulnerability.
|
|
30
|
+
* ***Do not*** attempt to show CI/CD vulnerabilities by creating new pull
|
|
31
|
+
requests to any of the Fastify organization's repositories. Doing so will
|
|
32
|
+
result in a [content report][cr] to GitHub as an unsolicited exploit.
|
|
33
|
+
The proper way to provide such reports is by creating a new repository,
|
|
34
|
+
configured in the same manner as the repository you would like to submit
|
|
35
|
+
a report about, and with a pull request to your own repository showing
|
|
36
|
+
the proof of concept.
|
|
37
|
+
|
|
38
|
+
[cr]: https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam#reporting-an-issue-or-pull-request
|
|
30
39
|
|
|
31
40
|
### Vulnerabilities found outside this process
|
|
32
41
|
|
|
@@ -13,8 +13,8 @@ open-source software and the limitations of existing communication channels.
|
|
|
13
13
|
|
|
14
14
|
But first, if we use a JavaScript framework to process incoming JSON data, take
|
|
15
15
|
a moment to read up on [Prototype Poisoning](https://medium.com/intrinsic/javascript-prototype-poisoning-vulnerabilities-in-the-wild-7bc15347c96)
|
|
16
|
-
in general, and the specific
|
|
17
|
-
(https://github.com/hapijs/hapi/issues/3916) of this issue.
|
|
16
|
+
in general, and the specific
|
|
17
|
+
[technical details](https://github.com/hapijs/hapi/issues/3916) of this issue.
|
|
18
18
|
This could be a critical issue so, we might need to verify your own code first.
|
|
19
19
|
It focuses on specific framework however, any solution that uses `JSON.parse()`
|
|
20
20
|
to process external data is potentially at risk.
|
package/docs/Reference/Errors.md
CHANGED
|
@@ -168,8 +168,6 @@ ajv.plugins option should be an array.
|
|
|
168
168
|
|
|
169
169
|
Version constraint should be a string.
|
|
170
170
|
|
|
171
|
-
<a name="FST_ERR_CTP_ALREADY_PRESENT"></a>
|
|
172
|
-
|
|
173
171
|
#### FST_ERR_CTP_ALREADY_PRESENT
|
|
174
172
|
<a id="FST_ERR_CTP_ALREADY_PRESENT"></a>
|
|
175
173
|
|
|
@@ -260,6 +258,11 @@ The hook name must be a string.
|
|
|
260
258
|
|
|
261
259
|
The hook callback must be a function.
|
|
262
260
|
|
|
261
|
+
#### FST_ERR_HOOK_INVALID_ASYNC_HANDLER
|
|
262
|
+
<a id="FST_ERR_HOOK_INVALID_ASYNC_HANDLER"></a>
|
|
263
|
+
|
|
264
|
+
Async function has too many arguments. Async hooks should not use the `done` argument.
|
|
265
|
+
|
|
263
266
|
#### FST_ERR_HOOK_NOT_SUPPORTED
|
|
264
267
|
<a id="FST_ERR_HOOK_NOT_SUPPORTED"></a>
|
|
265
268
|
|
|
@@ -271,8 +274,8 @@ The hook is not supported.
|
|
|
271
274
|
You must register a plugin for handling middlewares,
|
|
272
275
|
visit [`Middleware`](./Middleware.md) for more info.
|
|
273
276
|
|
|
274
|
-
<a name="FST_ERR_HOOK_TIMEOUT"></a>
|
|
275
277
|
#### FST_ERR_HOOK_TIMEOUT
|
|
278
|
+
<a id="FST_ERR_HOOK_TIMEOUT"></a>
|
|
276
279
|
|
|
277
280
|
A callback for a hook timed out
|
|
278
281
|
|
|
@@ -327,11 +330,21 @@ Called `reply.trailer` with an invalid header name.
|
|
|
327
330
|
|
|
328
331
|
Called `reply.trailer` with an invalid type. Expected a function.
|
|
329
332
|
|
|
333
|
+
#### FST_ERR_FAILED_ERROR_SERIALIZATION
|
|
334
|
+
<a id="FST_ERR_FAILED_ERROR_SERIALIZATION"></a>
|
|
335
|
+
|
|
336
|
+
Failed to serialize an error.
|
|
337
|
+
|
|
330
338
|
#### FST_ERR_MISSING_SERIALIZATION_FN
|
|
331
339
|
<a id="FST_ERR_MISSING_SERIALIZATION_FN"></a>
|
|
332
340
|
|
|
333
341
|
Missing serialization function.
|
|
334
342
|
|
|
343
|
+
#### FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN
|
|
344
|
+
<a id="FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN"></a>
|
|
345
|
+
|
|
346
|
+
Missing serialization function.
|
|
347
|
+
|
|
335
348
|
#### FST_ERR_REQ_INVALID_VALIDATION_INVOCATION
|
|
336
349
|
<a id="FST_ERR_REQ_INVALID_VALIDATION_INVOCATION"></a>
|
|
337
350
|
|
|
@@ -348,6 +361,11 @@ The schema provided does not have `$id` property.
|
|
|
348
361
|
|
|
349
362
|
A schema with the same `$id` already exists.
|
|
350
363
|
|
|
364
|
+
#### FST_ERR_SCH_CONTENT_MISSING_SCHEMA
|
|
365
|
+
<a id="FST_ERR_SCH_CONTENT_MISSING_SCHEMA"></a>
|
|
366
|
+
|
|
367
|
+
A schema is missing for the corresponding content type.
|
|
368
|
+
|
|
351
369
|
#### FST_ERR_SCH_DUPLICATE
|
|
352
370
|
<a id="FST_ERR_SCH_DUPLICATE"></a>
|
|
353
371
|
|
|
@@ -384,8 +402,8 @@ Invalid initialization options.
|
|
|
384
402
|
Cannot set forceCloseConnections to `idle` as your HTTP server
|
|
385
403
|
does not support `closeIdleConnections` method.
|
|
386
404
|
|
|
387
|
-
<a name="FST_ERR_DUPLICATED_ROUTE"></a>
|
|
388
405
|
#### FST_ERR_DUPLICATED_ROUTE
|
|
406
|
+
<a id="FST_ERR_DUPLICATED_ROUTE"></a>
|
|
389
407
|
|
|
390
408
|
The HTTP method already has a registered controller for that URL
|
|
391
409
|
|
|
@@ -394,7 +412,7 @@ The HTTP method already has a registered controller for that URL
|
|
|
394
412
|
|
|
395
413
|
The router received an invalid url.
|
|
396
414
|
|
|
397
|
-
|
|
415
|
+
#### FST_ERR_ASYNC_CONSTRAINT
|
|
398
416
|
<a id="FST_ERR_ASYNC_CONSTRAINT"></a>
|
|
399
417
|
|
|
400
418
|
The router received an error when using asynchronous constraints.
|
|
@@ -469,38 +487,42 @@ Fastify is already listening.
|
|
|
469
487
|
|
|
470
488
|
Installed Fastify plugin mismatched expected version.
|
|
471
489
|
|
|
472
|
-
<a name="FST_ERR_PLUGIN_CALLBACK_NOT_FN"></a>
|
|
473
|
-
|
|
474
490
|
#### FST_ERR_PLUGIN_CALLBACK_NOT_FN
|
|
491
|
+
<a id="FST_ERR_PLUGIN_CALLBACK_NOT_FN"></a>
|
|
475
492
|
|
|
476
493
|
Callback for a hook is not a function (mapped directly from `avvio`)
|
|
477
494
|
|
|
478
|
-
<a name="FST_ERR_PLUGIN_NOT_VALID"></a>
|
|
479
|
-
|
|
480
495
|
#### FST_ERR_PLUGIN_NOT_VALID
|
|
496
|
+
<a id="FST_ERR_PLUGIN_NOT_VALID"></a>
|
|
481
497
|
|
|
482
498
|
Plugin must be a function or a promise.
|
|
483
499
|
|
|
484
|
-
<a name="FST_ERR_ROOT_PLG_BOOTED"></a>
|
|
485
|
-
|
|
486
500
|
#### FST_ERR_ROOT_PLG_BOOTED
|
|
501
|
+
<a id="FST_ERR_ROOT_PLG_BOOTED"></a>
|
|
487
502
|
|
|
488
503
|
Root plugin has already booted (mapped directly from `avvio`)
|
|
489
504
|
|
|
490
|
-
<a name="FST_ERR_PARENT_PLUGIN_BOOTED"></a>
|
|
491
|
-
|
|
492
505
|
#### FST_ERR_PARENT_PLUGIN_BOOTED
|
|
506
|
+
<a id="FST_ERR_PARENT_PLUGIN_BOOTED"></a>
|
|
493
507
|
|
|
494
508
|
Impossible to load plugin because the parent (mapped directly from `avvio`)
|
|
495
509
|
|
|
496
|
-
<a name="FST_ERR_PLUGIN_TIMEOUT"></a>
|
|
497
|
-
|
|
498
510
|
#### FST_ERR_PLUGIN_TIMEOUT
|
|
511
|
+
<a id="FST_ERR_PLUGIN_TIMEOUT"></a>
|
|
499
512
|
|
|
500
513
|
Plugin did not start in time. Default timeout (in millis): `10000`
|
|
501
514
|
|
|
502
|
-
<a name="FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE"></a>
|
|
503
|
-
|
|
504
515
|
#### FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE
|
|
516
|
+
<a id="FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE"></a>
|
|
505
517
|
|
|
506
518
|
The decorator is not present in the instance.
|
|
519
|
+
|
|
520
|
+
#### FST_ERR_VALIDATION
|
|
521
|
+
<a id="FST_ERR_VALIDATION"></a>
|
|
522
|
+
|
|
523
|
+
The Request failed the payload validation.
|
|
524
|
+
|
|
525
|
+
#### FST_ERR_LISTEN_OPTIONS_INVALID
|
|
526
|
+
<a id="FST_ERR_LISTEN_OPTIONS_INVALID"></a>
|
|
527
|
+
|
|
528
|
+
Invalid listen options.
|
|
@@ -196,7 +196,7 @@ app.addHook('preHandler', function (req, reply, done) {
|
|
|
196
196
|
})
|
|
197
197
|
```
|
|
198
198
|
|
|
199
|
-
**Note**: Care should be
|
|
199
|
+
**Note**: Care should be taken to ensure serializers never throw, as an error
|
|
200
200
|
thrown from a serializer has the potential to cause the Node process to exit.
|
|
201
201
|
See the [Pino documentation](https://getpino.io/#/docs/api?id=opt-serializers)
|
|
202
202
|
on serializers for more information.
|
|
@@ -145,6 +145,10 @@ await fastify.ready()
|
|
|
145
145
|
|
|
146
146
|
await fastify.listen({ port: 3000 })
|
|
147
147
|
```
|
|
148
|
+
*Note: Using `await` when registering a plugin loads the plugin
|
|
149
|
+
and the underlying dependency tree, "finalizing" the encapsulation process.
|
|
150
|
+
Any mutations to the plugin after it and its dependencies have been
|
|
151
|
+
loaded will not be reflected in the parent instance.*
|
|
148
152
|
|
|
149
153
|
#### ESM support
|
|
150
154
|
<a id="esm-support"></a>
|
package/docs/Reference/Routes.md
CHANGED
|
@@ -90,6 +90,14 @@ fastify.route(options)
|
|
|
90
90
|
To access the default handler, you can access `instance.errorHandler`. Note
|
|
91
91
|
that this will point to fastify's default `errorHandler` only if a plugin
|
|
92
92
|
hasn't overridden it already.
|
|
93
|
+
* `childLoggerFactory(logger, binding, opts, rawReq)`: a custom factory function
|
|
94
|
+
that will be called to produce a child logger instance for every request.
|
|
95
|
+
See [`childLoggerFactory`](./Server.md#childloggerfactory) for more info.
|
|
96
|
+
Overrides the default logger factory, and anything set by
|
|
97
|
+
[`setChildLoggerFactory`](./Server.md#setchildloggerfactory), for requests to
|
|
98
|
+
the route. To access the default factory, you can access
|
|
99
|
+
`instance.childLoggerFactory`. Note that this will point to Fastify's default
|
|
100
|
+
`childLoggerFactory` only if a plugin hasn't overridden it already.
|
|
93
101
|
* `validatorCompiler({ schema, method, url, httpPart })`: function that builds
|
|
94
102
|
schemas for request validations. See the [Validation and
|
|
95
103
|
Serialization](./Validation-and-Serialization.md#schema-validator)
|
package/docs/Reference/Server.md
CHANGED
|
@@ -80,6 +80,7 @@ describes the properties available in that options object.
|
|
|
80
80
|
- [schemaController](#schemacontroller)
|
|
81
81
|
- [setNotFoundHandler](#setnotfoundhandler)
|
|
82
82
|
- [setErrorHandler](#seterrorhandler)
|
|
83
|
+
- [setChildLoggerFactory](#setchildloggerfactory)
|
|
83
84
|
- [addConstraintStrategy](#addconstraintstrategy)
|
|
84
85
|
- [hasConstraintStrategy](#hasconstraintstrategy)
|
|
85
86
|
- [printRoutes](#printroutes)
|
|
@@ -91,6 +92,7 @@ describes the properties available in that options object.
|
|
|
91
92
|
- [getDefaultJsonParser](#getdefaultjsonparser)
|
|
92
93
|
- [defaultTextParser](#defaulttextparser)
|
|
93
94
|
- [errorHandler](#errorhandler)
|
|
95
|
+
- [childLoggerFactory](#childloggerfactory)
|
|
94
96
|
- [initialConfig](#initialconfig)
|
|
95
97
|
|
|
96
98
|
### `http`
|
|
@@ -1537,6 +1539,35 @@ if (statusCode >= 500) {
|
|
|
1537
1539
|
log.error(error)
|
|
1538
1540
|
}
|
|
1539
1541
|
```
|
|
1542
|
+
#### setChildLoggerFactory
|
|
1543
|
+
<a id="set-child-logger-factory"></a>
|
|
1544
|
+
|
|
1545
|
+
`fastify.setChildLoggerFactory(factory(logger, bindings, opts, rawReq))`: Set a
|
|
1546
|
+
function that will be called when creating a child logger instance for each request
|
|
1547
|
+
which allows for modifying or adding child logger bindings and logger options, or
|
|
1548
|
+
returning a completely custom child logger implementation.
|
|
1549
|
+
|
|
1550
|
+
Child logger bindings have a performance advantage over per-log bindings, because
|
|
1551
|
+
they are pre-serialised by Pino when the child logger is created.
|
|
1552
|
+
|
|
1553
|
+
The first parameter is the parent logger instance, followed by the default bindings
|
|
1554
|
+
and logger options which should be passed to the child logger, and finally
|
|
1555
|
+
the raw request (not a Fastify request object). The function is bound with `this`
|
|
1556
|
+
being the Fastify instance.
|
|
1557
|
+
|
|
1558
|
+
For example:
|
|
1559
|
+
```js
|
|
1560
|
+
const fastify = require('fastify')({
|
|
1561
|
+
childLoggerFactory: function (logger, bindings, opts, rawReq) {
|
|
1562
|
+
// Calculate additional bindings from the request if needed
|
|
1563
|
+
bindings.traceContext = rawReq.headers['x-cloud-trace-context']
|
|
1564
|
+
return logger.child(bindings, opts)
|
|
1565
|
+
}
|
|
1566
|
+
})
|
|
1567
|
+
```
|
|
1568
|
+
|
|
1569
|
+
The handler is bound to the Fastify instance and is fully encapsulated, so
|
|
1570
|
+
different plugins can set different logger factories.
|
|
1540
1571
|
|
|
1541
1572
|
#### addConstraintStrategy
|
|
1542
1573
|
<a id="addConstraintStrategy"></a>
|
|
@@ -1810,6 +1841,13 @@ fastify.get('/', {
|
|
|
1810
1841
|
}, handler)
|
|
1811
1842
|
```
|
|
1812
1843
|
|
|
1844
|
+
#### childLoggerFactory
|
|
1845
|
+
<a id="childLoggerFactory"></a>
|
|
1846
|
+
|
|
1847
|
+
`fastify.childLoggerFactory` returns the custom logger factory function for the
|
|
1848
|
+
Fastify instance. See the [`childLoggerFactory` config option](#setchildloggerfactory)
|
|
1849
|
+
for more info.
|
|
1850
|
+
|
|
1813
1851
|
#### initialConfig
|
|
1814
1852
|
<a id="initial-config"></a>
|
|
1815
1853
|
|
package/fastify.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { FastifyContext, FastifyContextConfig } from './types/context'
|
|
|
14
14
|
import { FastifyErrorCodes } from './types/errors'
|
|
15
15
|
import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler } from './types/hooks'
|
|
16
16
|
import { FastifyListenOptions, FastifyInstance, PrintRoutesOptions } from './types/instance'
|
|
17
|
-
import { FastifyBaseLogger, FastifyLoggerInstance, FastifyLoggerOptions, PinoLoggerOptions, FastifyLogFn, LogLevel } from './types/logger'
|
|
17
|
+
import { FastifyBaseLogger, FastifyLoggerInstance, FastifyLoggerOptions, PinoLoggerOptions, FastifyLogFn, LogLevel, Bindings, ChildLoggerOptions } from './types/logger'
|
|
18
18
|
import { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin } from './types/plugin'
|
|
19
19
|
import { FastifyRegister, FastifyRegisterOptions, RegisterOptions } from './types/register'
|
|
20
20
|
import { FastifyReply } from './types/reply'
|
|
@@ -106,6 +106,7 @@ declare namespace fastify {
|
|
|
106
106
|
serializerOpts?: FJSOptions | Record<string, unknown>,
|
|
107
107
|
serverFactory?: FastifyServerFactory<RawServer>,
|
|
108
108
|
caseSensitive?: boolean,
|
|
109
|
+
allowUnsafeRegex?: boolean,
|
|
109
110
|
requestIdHeader?: string | false,
|
|
110
111
|
requestIdLogLabel?: string;
|
|
111
112
|
jsonShorthand?: boolean;
|
|
@@ -158,7 +159,7 @@ declare namespace fastify {
|
|
|
158
159
|
/**
|
|
159
160
|
* listener to error events emitted by client connections
|
|
160
161
|
*/
|
|
161
|
-
clientErrorHandler?: (error: ConnectionError, socket: Socket) => void
|
|
162
|
+
clientErrorHandler?: (error: ConnectionError, socket: Socket) => void,
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
export interface ValidationResult {
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.20.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('http')
|
|
@@ -28,20 +28,21 @@ const {
|
|
|
28
28
|
kSchemaErrorFormatter,
|
|
29
29
|
kErrorHandler,
|
|
30
30
|
kKeepAliveConnections,
|
|
31
|
-
|
|
31
|
+
kChildLoggerFactory
|
|
32
32
|
} = require('./lib/symbols.js')
|
|
33
33
|
|
|
34
34
|
const { createServer, compileValidateHTTPVersion } = require('./lib/server')
|
|
35
35
|
const Reply = require('./lib/reply')
|
|
36
36
|
const Request = require('./lib/request')
|
|
37
|
+
const Context = require('./lib/context.js')
|
|
37
38
|
const { supportedMethods } = require('./lib/httpMethods')
|
|
38
39
|
const decorator = require('./lib/decorate')
|
|
39
40
|
const ContentTypeParser = require('./lib/contentTypeParser')
|
|
40
41
|
const SchemaController = require('./lib/schema-controller')
|
|
41
42
|
const { Hooks, hookRunnerApplication, supportedHooks } = require('./lib/hooks')
|
|
42
|
-
const { createLogger } = require('./lib/logger')
|
|
43
|
+
const { createLogger, createChildLogger, defaultChildLoggerFactory } = require('./lib/logger')
|
|
43
44
|
const pluginUtils = require('./lib/pluginUtils')
|
|
44
|
-
const reqIdGenFactory = require('./lib/reqIdGenFactory')
|
|
45
|
+
const { reqIdGenFactory } = require('./lib/reqIdGenFactory')
|
|
45
46
|
const { buildRouting, validateBodyLimitOption } = require('./lib/route')
|
|
46
47
|
const build404 = require('./lib/fourOhFour')
|
|
47
48
|
const getSecuredInitialConfig = require('./lib/initialConfigValidation')
|
|
@@ -74,14 +75,6 @@ const {
|
|
|
74
75
|
|
|
75
76
|
const { buildErrorHandler } = require('./lib/error-handler.js')
|
|
76
77
|
|
|
77
|
-
const onBadUrlContext = {
|
|
78
|
-
config: {
|
|
79
|
-
},
|
|
80
|
-
onSend: [],
|
|
81
|
-
onError: [],
|
|
82
|
-
[kFourOhFourContext]: null
|
|
83
|
-
}
|
|
84
|
-
|
|
85
78
|
function defaultBuildPrettyMeta (route) {
|
|
86
79
|
// return a shallow copy of route's sanitized context
|
|
87
80
|
|
|
@@ -95,6 +88,9 @@ function defaultBuildPrettyMeta (route) {
|
|
|
95
88
|
return Object.assign({}, cleanKeys)
|
|
96
89
|
}
|
|
97
90
|
|
|
91
|
+
/**
|
|
92
|
+
* @param {import('./fastify.js').FastifyServerOptions} options
|
|
93
|
+
*/
|
|
98
94
|
function fastify (options) {
|
|
99
95
|
// Options validations
|
|
100
96
|
options = options || {}
|
|
@@ -113,7 +109,7 @@ function fastify (options) {
|
|
|
113
109
|
|
|
114
110
|
validateBodyLimitOption(options.bodyLimit)
|
|
115
111
|
|
|
116
|
-
const requestIdHeader = (options.requestIdHeader === false) ? false : (options.requestIdHeader || defaultInitOptions.requestIdHeader)
|
|
112
|
+
const requestIdHeader = (options.requestIdHeader === false) ? false : (options.requestIdHeader || defaultInitOptions.requestIdHeader).toLowerCase()
|
|
117
113
|
const genReqId = reqIdGenFactory(requestIdHeader, options.genReqId)
|
|
118
114
|
const requestIdLogLabel = options.requestIdLogLabel || 'reqId'
|
|
119
115
|
const bodyLimit = options.bodyLimit || defaultInitOptions.bodyLimit
|
|
@@ -235,6 +231,7 @@ function fastify (options) {
|
|
|
235
231
|
[kSchemaController]: schemaController,
|
|
236
232
|
[kSchemaErrorFormatter]: null,
|
|
237
233
|
[kErrorHandler]: buildErrorHandler(),
|
|
234
|
+
[kChildLoggerFactory]: defaultChildLoggerFactory,
|
|
238
235
|
[kReplySerializerDefault]: null,
|
|
239
236
|
[kContentTypeParser]: new ContentTypeParser(
|
|
240
237
|
bodyLimit,
|
|
@@ -340,6 +337,8 @@ function fastify (options) {
|
|
|
340
337
|
// custom error handling
|
|
341
338
|
setNotFoundHandler,
|
|
342
339
|
setErrorHandler,
|
|
340
|
+
// child logger
|
|
341
|
+
setChildLoggerFactory,
|
|
343
342
|
// Set fastify initial configuration options read-only object
|
|
344
343
|
initialConfig,
|
|
345
344
|
// constraint strategies
|
|
@@ -351,11 +350,13 @@ function fastify (options) {
|
|
|
351
350
|
listeningOrigin: {
|
|
352
351
|
get () {
|
|
353
352
|
const address = this.addresses().slice(-1).pop()
|
|
354
|
-
/*
|
|
353
|
+
/* ignore if windows: unix socket is not testable on Windows platform */
|
|
354
|
+
/* c8 ignore next 3 */
|
|
355
355
|
if (typeof address === 'string') {
|
|
356
356
|
return address
|
|
357
357
|
}
|
|
358
|
-
|
|
358
|
+
const host = address.family === 'IPv6' ? `[${address.address}]` : address.address
|
|
359
|
+
return `${this[kOptions].https ? 'https' : 'http'}://${host}:${address.port}`
|
|
359
360
|
}
|
|
360
361
|
},
|
|
361
362
|
pluginName: {
|
|
@@ -379,6 +380,10 @@ function fastify (options) {
|
|
|
379
380
|
configurable: true,
|
|
380
381
|
get () { return this[kSchemaController].getSerializerCompiler() }
|
|
381
382
|
},
|
|
383
|
+
childLoggerFactory: {
|
|
384
|
+
configurable: true,
|
|
385
|
+
get () { return this[kChildLoggerFactory] }
|
|
386
|
+
},
|
|
382
387
|
version: {
|
|
383
388
|
configurable: true,
|
|
384
389
|
get () { return VERSION }
|
|
@@ -452,6 +457,7 @@ function fastify (options) {
|
|
|
452
457
|
// https://github.com/nodejs/node/issues/48604
|
|
453
458
|
if (!options.serverFactory || fastify[kState].listening) {
|
|
454
459
|
instance.server.close(function (err) {
|
|
460
|
+
/* c8 ignore next 6 */
|
|
455
461
|
if (err && err.code !== 'ERR_SERVER_NOT_RUNNING') {
|
|
456
462
|
done(null)
|
|
457
463
|
} else {
|
|
@@ -465,6 +471,12 @@ function fastify (options) {
|
|
|
465
471
|
})
|
|
466
472
|
})
|
|
467
473
|
|
|
474
|
+
// Create bad URL context
|
|
475
|
+
const onBadUrlContext = new Context({
|
|
476
|
+
server: fastify,
|
|
477
|
+
config: {}
|
|
478
|
+
})
|
|
479
|
+
|
|
468
480
|
// Set the default 404 handler
|
|
469
481
|
fastify.setNotFoundHandler()
|
|
470
482
|
fourOhFour.arrange404(fastify)
|
|
@@ -706,7 +718,7 @@ function fastify (options) {
|
|
|
706
718
|
function onBadUrl (path, req, res) {
|
|
707
719
|
if (frameworkErrors) {
|
|
708
720
|
const id = genReqId(req)
|
|
709
|
-
const childLogger =
|
|
721
|
+
const childLogger = createChildLogger(onBadUrlContext, logger, req, id)
|
|
710
722
|
|
|
711
723
|
const request = new Request(id, null, req, null, childLogger, onBadUrlContext)
|
|
712
724
|
const reply = new Reply(res, request, childLogger)
|
|
@@ -731,7 +743,7 @@ function fastify (options) {
|
|
|
731
743
|
if (err) {
|
|
732
744
|
if (frameworkErrors) {
|
|
733
745
|
const id = genReqId(req)
|
|
734
|
-
const childLogger =
|
|
746
|
+
const childLogger = createChildLogger(onBadUrlContext, logger, req, id)
|
|
735
747
|
|
|
736
748
|
const request = new Request(id, null, req, null, childLogger, onBadUrlContext)
|
|
737
749
|
const reply = new Reply(res, request, childLogger)
|
|
@@ -803,6 +815,13 @@ function fastify (options) {
|
|
|
803
815
|
return this
|
|
804
816
|
}
|
|
805
817
|
|
|
818
|
+
function setChildLoggerFactory (factory) {
|
|
819
|
+
throwIfAlreadyStarted('Cannot call "setChildLoggerFactory"!')
|
|
820
|
+
|
|
821
|
+
this[kChildLoggerFactory] = factory
|
|
822
|
+
return this
|
|
823
|
+
}
|
|
824
|
+
|
|
806
825
|
function printRoutes (opts = {}) {
|
|
807
826
|
// includeHooks:true - shortcut to include all supported hooks exported by fastify.Hooks
|
|
808
827
|
opts.includeMeta = opts.includeHooks ? opts.includeMeta ? supportedHooks.concat(opts.includeMeta) : supportedHooks : opts.includeMeta
|
package/lib/context.js
CHANGED
|
@@ -5,6 +5,8 @@ const {
|
|
|
5
5
|
kReplySerializerDefault,
|
|
6
6
|
kSchemaErrorFormatter,
|
|
7
7
|
kErrorHandler,
|
|
8
|
+
kChildLoggerFactory,
|
|
9
|
+
kOptions,
|
|
8
10
|
kReply,
|
|
9
11
|
kRequest,
|
|
10
12
|
kBodyLimit,
|
|
@@ -22,6 +24,8 @@ function Context ({
|
|
|
22
24
|
schema,
|
|
23
25
|
handler,
|
|
24
26
|
config,
|
|
27
|
+
requestIdLogLabel,
|
|
28
|
+
childLoggerFactory,
|
|
25
29
|
errorHandler,
|
|
26
30
|
bodyLimit,
|
|
27
31
|
logLevel,
|
|
@@ -51,6 +55,8 @@ function Context ({
|
|
|
51
55
|
this.onRequestAbort = null
|
|
52
56
|
this.config = config
|
|
53
57
|
this.errorHandler = errorHandler || server[kErrorHandler]
|
|
58
|
+
this.requestIdLogLabel = requestIdLogLabel || server[kOptions].requestIdLogLabel
|
|
59
|
+
this.childLoggerFactory = childLoggerFactory || server[kChildLoggerFactory]
|
|
54
60
|
this._middie = null
|
|
55
61
|
this._parserOptions = {
|
|
56
62
|
limit: bodyLimit || server[kBodyLimit]
|
package/lib/errors.js
CHANGED
|
@@ -20,32 +20,49 @@ const codes = {
|
|
|
20
20
|
FST_ERR_QSP_NOT_FN: createError(
|
|
21
21
|
'FST_ERR_QSP_NOT_FN',
|
|
22
22
|
"querystringParser option should be a function, instead got '%s'",
|
|
23
|
-
500
|
|
23
|
+
500,
|
|
24
|
+
TypeError
|
|
24
25
|
),
|
|
25
26
|
FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN: createError(
|
|
26
27
|
'FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN',
|
|
27
28
|
"schemaController.bucket option should be a function, instead got '%s'",
|
|
28
|
-
500
|
|
29
|
+
500,
|
|
30
|
+
TypeError
|
|
29
31
|
),
|
|
30
32
|
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN: createError(
|
|
31
33
|
'FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN',
|
|
32
34
|
"schemaErrorFormatter option should be a non async function. Instead got '%s'.",
|
|
33
|
-
500
|
|
35
|
+
500,
|
|
36
|
+
TypeError
|
|
34
37
|
),
|
|
35
38
|
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ: createError(
|
|
36
39
|
'FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ',
|
|
37
|
-
"
|
|
38
|
-
500
|
|
40
|
+
"ajv.customOptions option should be an object, instead got '%s'",
|
|
41
|
+
500,
|
|
42
|
+
TypeError
|
|
39
43
|
),
|
|
40
44
|
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR: createError(
|
|
41
45
|
'FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR',
|
|
42
|
-
"
|
|
43
|
-
500
|
|
46
|
+
"ajv.plugins option should be an array, instead got '%s'",
|
|
47
|
+
500,
|
|
48
|
+
TypeError
|
|
44
49
|
),
|
|
45
50
|
FST_ERR_VERSION_CONSTRAINT_NOT_STR: createError(
|
|
46
51
|
'FST_ERR_VERSION_CONSTRAINT_NOT_STR',
|
|
47
52
|
'Version constraint should be a string.',
|
|
48
|
-
500
|
|
53
|
+
500,
|
|
54
|
+
TypeError
|
|
55
|
+
),
|
|
56
|
+
FST_ERR_VALIDATION: createError(
|
|
57
|
+
'FST_ERR_VALIDATION',
|
|
58
|
+
'%s',
|
|
59
|
+
400
|
|
60
|
+
),
|
|
61
|
+
FST_ERR_LISTEN_OPTIONS_INVALID: createError(
|
|
62
|
+
'FST_ERR_LISTEN_OPTIONS_INVALID',
|
|
63
|
+
"Invalid listen options: '%s'",
|
|
64
|
+
500,
|
|
65
|
+
TypeError
|
|
49
66
|
),
|
|
50
67
|
|
|
51
68
|
/**
|
|
@@ -116,7 +133,9 @@ const codes = {
|
|
|
116
133
|
),
|
|
117
134
|
FST_ERR_DEC_DEPENDENCY_INVALID_TYPE: createError(
|
|
118
135
|
'FST_ERR_DEC_DEPENDENCY_INVALID_TYPE',
|
|
119
|
-
"The dependencies of decorator '%s' must be of type Array."
|
|
136
|
+
"The dependencies of decorator '%s' must be of type Array.",
|
|
137
|
+
500,
|
|
138
|
+
TypeError
|
|
120
139
|
),
|
|
121
140
|
FST_ERR_DEC_MISSING_DEPENDENCY: createError(
|
|
122
141
|
'FST_ERR_DEC_MISSING_DEPENDENCY',
|
|
@@ -179,7 +198,9 @@ const codes = {
|
|
|
179
198
|
|
|
180
199
|
FST_ERR_LOG_INVALID_LOGGER: createError(
|
|
181
200
|
'FST_ERR_LOG_INVALID_LOGGER',
|
|
182
|
-
"Invalid logger object provided. The logger instance should have these functions(s): '%s'."
|
|
201
|
+
"Invalid logger object provided. The logger instance should have these functions(s): '%s'.",
|
|
202
|
+
500,
|
|
203
|
+
TypeError
|
|
183
204
|
),
|
|
184
205
|
|
|
185
206
|
/**
|
|
@@ -197,7 +218,9 @@ const codes = {
|
|
|
197
218
|
),
|
|
198
219
|
FST_ERR_REP_SENT_VALUE: createError(
|
|
199
220
|
'FST_ERR_REP_SENT_VALUE',
|
|
200
|
-
'The only possible value for reply.sent is true.'
|
|
221
|
+
'The only possible value for reply.sent is true.',
|
|
222
|
+
500,
|
|
223
|
+
TypeError
|
|
201
224
|
),
|
|
202
225
|
FST_ERR_SEND_INSIDE_ONERR: createError(
|
|
203
226
|
'FST_ERR_SEND_INSIDE_ONERR',
|
|
@@ -298,7 +321,8 @@ const codes = {
|
|
|
298
321
|
FST_ERR_BAD_URL: createError(
|
|
299
322
|
'FST_ERR_BAD_URL',
|
|
300
323
|
"'%s' is not a valid url component",
|
|
301
|
-
400
|
|
324
|
+
400,
|
|
325
|
+
URIError
|
|
302
326
|
),
|
|
303
327
|
FST_ERR_ASYNC_CONSTRAINT: createError(
|
|
304
328
|
'FST_ERR_ASYNC_CONSTRAINT',
|
|
@@ -314,12 +338,14 @@ const codes = {
|
|
|
314
338
|
FST_ERR_INVALID_URL: createError(
|
|
315
339
|
'FST_ERR_INVALID_URL',
|
|
316
340
|
"URL must be a string. Received '%s'",
|
|
317
|
-
400
|
|
341
|
+
400,
|
|
342
|
+
TypeError
|
|
318
343
|
),
|
|
319
344
|
FST_ERR_ROUTE_OPTIONS_NOT_OBJ: createError(
|
|
320
345
|
'FST_ERR_ROUTE_OPTIONS_NOT_OBJ',
|
|
321
346
|
'Options for "%s:%s" route must be an object',
|
|
322
|
-
500
|
|
347
|
+
500,
|
|
348
|
+
TypeError
|
|
323
349
|
),
|
|
324
350
|
FST_ERR_ROUTE_DUPLICATED_HANDLER: createError(
|
|
325
351
|
'FST_ERR_ROUTE_DUPLICATED_HANDLER',
|
|
@@ -329,7 +355,8 @@ const codes = {
|
|
|
329
355
|
FST_ERR_ROUTE_HANDLER_NOT_FN: createError(
|
|
330
356
|
'FST_ERR_ROUTE_HANDLER_NOT_FN',
|
|
331
357
|
'Error Handler for %s:%s route, if defined, must be a function',
|
|
332
|
-
500
|
|
358
|
+
500,
|
|
359
|
+
TypeError
|
|
333
360
|
),
|
|
334
361
|
FST_ERR_ROUTE_MISSING_HANDLER: createError(
|
|
335
362
|
'FST_ERR_ROUTE_MISSING_HANDLER',
|
|
@@ -339,7 +366,8 @@ const codes = {
|
|
|
339
366
|
FST_ERR_ROUTE_METHOD_INVALID: createError(
|
|
340
367
|
'FST_ERR_ROUTE_METHOD_INVALID',
|
|
341
368
|
'Provided method is invalid!',
|
|
342
|
-
500
|
|
369
|
+
500,
|
|
370
|
+
TypeError
|
|
343
371
|
),
|
|
344
372
|
FST_ERR_ROUTE_METHOD_NOT_SUPPORTED: createError(
|
|
345
373
|
'FST_ERR_ROUTE_METHOD_NOT_SUPPORTED',
|
|
@@ -358,9 +386,10 @@ const codes = {
|
|
|
358
386
|
TypeError
|
|
359
387
|
),
|
|
360
388
|
FST_ERR_ROUTE_REWRITE_NOT_STR: createError(
|
|
361
|
-
'
|
|
389
|
+
'FST_ERR_ROUTE_REWRITE_NOT_STR',
|
|
362
390
|
'Rewrite url for "%s" needs to be of type "string" but received "%s"',
|
|
363
|
-
500
|
|
391
|
+
500,
|
|
392
|
+
TypeError
|
|
364
393
|
),
|
|
365
394
|
|
|
366
395
|
/**
|
|
@@ -396,7 +425,9 @@ const codes = {
|
|
|
396
425
|
*/
|
|
397
426
|
FST_ERR_PLUGIN_CALLBACK_NOT_FN: createError(
|
|
398
427
|
'FST_ERR_PLUGIN_CALLBACK_NOT_FN',
|
|
399
|
-
'fastify-plugin: %s'
|
|
428
|
+
'fastify-plugin: %s',
|
|
429
|
+
500,
|
|
430
|
+
TypeError
|
|
400
431
|
),
|
|
401
432
|
FST_ERR_PLUGIN_NOT_VALID: createError(
|
|
402
433
|
'FST_ERR_PLUGIN_NOT_VALID',
|