fastify 3.26.0 → 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/build/build-error-serializer.js +27 -0
- package/build/build-validation.js +49 -35
- package/docs/Guides/Ecosystem.md +2 -1
- package/docs/Guides/Prototype-Poisoning.md +3 -3
- package/docs/Migration-Guide-V4.md +12 -0
- package/docs/Reference/ContentTypeParser.md +8 -1
- package/docs/Reference/Errors.md +51 -6
- package/docs/Reference/Hooks.md +4 -7
- package/docs/Reference/LTS.md +5 -4
- package/docs/Reference/Reply.md +23 -22
- package/docs/Reference/Request.md +1 -3
- package/docs/Reference/Routes.md +17 -10
- package/docs/Reference/Server.md +98 -63
- package/docs/Reference/TypeScript.md +11 -13
- package/docs/Reference/Validation-and-Serialization.md +32 -54
- package/docs/Type-Providers.md +257 -0
- package/examples/hooks.js +1 -1
- package/examples/simple-stream.js +18 -0
- package/fastify.d.ts +36 -22
- package/fastify.js +72 -53
- package/lib/configValidator.js +902 -1023
- package/lib/contentTypeParser.js +6 -16
- package/lib/context.js +36 -10
- package/lib/decorate.js +5 -3
- package/lib/error-handler.js +158 -0
- package/lib/error-serializer.js +257 -0
- package/lib/errors.js +49 -10
- package/lib/fourOhFour.js +31 -20
- package/lib/handleRequest.js +10 -13
- package/lib/hooks.js +14 -9
- package/lib/noop-set.js +10 -0
- package/lib/pluginOverride.js +0 -3
- package/lib/pluginUtils.js +3 -2
- package/lib/reply.js +44 -163
- package/lib/request.js +13 -10
- package/lib/route.js +158 -139
- package/lib/schema-controller.js +3 -3
- package/lib/schemas.js +27 -1
- package/lib/server.js +219 -116
- package/lib/symbols.js +6 -4
- package/lib/validation.js +2 -1
- package/lib/warnings.js +2 -12
- package/lib/wrapThenable.js +4 -11
- package/package.json +40 -45
- package/test/404s.test.js +265 -108
- package/test/500s.test.js +2 -2
- package/test/async-await.test.js +15 -71
- package/test/close.test.js +39 -1
- package/test/content-parser.test.js +32 -0
- package/test/context-config.test.js +56 -4
- package/test/custom-http-server.test.js +14 -7
- package/test/custom-parser-async.test.js +0 -65
- package/test/custom-parser.test.js +54 -121
- package/test/decorator.test.js +1 -3
- package/test/delete.test.js +5 -5
- package/test/encapsulated-error-handler.test.js +50 -0
- package/test/esm/index.test.js +0 -14
- package/test/fastify-instance.test.js +4 -4
- package/test/fluent-schema.test.js +4 -4
- package/test/get.test.js +3 -3
- package/test/helper.js +18 -3
- package/test/hooks-async.test.js +14 -47
- package/test/hooks.on-ready.test.js +9 -4
- package/test/hooks.test.js +58 -99
- package/test/http2/closing.test.js +5 -11
- package/test/http2/unknown-http-method.test.js +3 -9
- package/test/https/custom-https-server.test.js +12 -6
- package/test/inject.test.js +1 -1
- package/test/input-validation.js +2 -2
- package/test/internals/all.test.js +2 -2
- package/test/internals/contentTypeParser.test.js +4 -4
- package/test/internals/handleRequest.test.js +9 -46
- package/test/internals/initialConfig.test.js +33 -12
- package/test/internals/logger.test.js +1 -1
- package/test/internals/reply.test.js +245 -3
- package/test/internals/request.test.js +13 -7
- package/test/internals/server.test.js +88 -0
- package/test/listen.test.js +84 -1
- package/test/logger.test.js +98 -58
- package/test/maxRequestsPerSocket.test.js +8 -6
- package/test/middleware.test.js +2 -25
- package/test/noop-set.test.js +19 -0
- package/test/nullable-validation.test.js +51 -14
- package/test/plugin.test.js +31 -5
- package/test/pretty-print.test.js +22 -10
- package/test/reply-error.test.js +123 -12
- package/test/request-error.test.js +2 -5
- package/test/route-hooks.test.js +17 -17
- package/test/route-prefix.test.js +2 -1
- package/test/route.test.js +216 -20
- package/test/router-options.test.js +1 -1
- package/test/schema-examples.test.js +11 -5
- package/test/schema-feature.test.js +24 -19
- package/test/schema-serialization.test.js +50 -9
- package/test/schema-special-usage.test.js +14 -81
- package/test/schema-validation.test.js +9 -9
- package/test/skip-reply-send.test.js +8 -8
- package/test/stream.test.js +23 -12
- package/test/throw.test.js +8 -5
- package/test/trust-proxy.test.js +1 -1
- package/test/type-provider.test.js +20 -0
- package/test/types/fastify.test-d.ts +12 -18
- package/test/types/hooks.test-d.ts +7 -3
- package/test/types/import.js +2 -0
- package/test/types/import.ts +1 -0
- package/test/types/instance.test-d.ts +61 -15
- package/test/types/logger.test-d.ts +44 -15
- package/test/types/route.test-d.ts +8 -2
- package/test/types/schema.test-d.ts +2 -39
- package/test/types/type-provider.test-d.ts +417 -0
- package/test/validation-error-handling.test.js +9 -9
- package/test/versioned-routes.test.js +29 -17
- package/test/wrapThenable.test.js +7 -6
- package/types/.eslintrc.json +1 -1
- package/types/content-type-parser.d.ts +17 -8
- package/types/hooks.d.ts +107 -60
- package/types/instance.d.ts +137 -105
- package/types/logger.d.ts +18 -104
- package/types/plugin.d.ts +10 -4
- package/types/register.d.ts +1 -1
- package/types/reply.d.ts +16 -11
- package/types/request.d.ts +10 -5
- package/types/route.d.ts +42 -31
- package/types/schema.d.ts +15 -1
- package/types/type-provider.d.ts +99 -0
- package/types/utils.d.ts +1 -1
- package/lib/schema-compilers.js +0 -12
- package/test/emit-warning.test.js +0 -166
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '
|
|
3
|
+
const VERSION = '4.0.0-alpha.1'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('http')
|
|
@@ -10,6 +10,7 @@ let lightMyRequest
|
|
|
10
10
|
const {
|
|
11
11
|
kAvvioBoot,
|
|
12
12
|
kChildren,
|
|
13
|
+
kServerBindings,
|
|
13
14
|
kBodyLimit,
|
|
14
15
|
kRoutePrefix,
|
|
15
16
|
kLogLevel,
|
|
@@ -26,10 +27,12 @@ const {
|
|
|
26
27
|
kOptions,
|
|
27
28
|
kPluginNameChain,
|
|
28
29
|
kSchemaErrorFormatter,
|
|
29
|
-
kErrorHandler
|
|
30
|
+
kErrorHandler,
|
|
31
|
+
kKeepAliveConnections,
|
|
32
|
+
kFourOhFourContext
|
|
30
33
|
} = require('./lib/symbols.js')
|
|
31
34
|
|
|
32
|
-
const
|
|
35
|
+
const createServer = require('./lib/server')
|
|
33
36
|
const Reply = require('./lib/reply')
|
|
34
37
|
const Request = require('./lib/request')
|
|
35
38
|
const supportedMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTIONS']
|
|
@@ -45,18 +48,23 @@ const build404 = require('./lib/fourOhFour')
|
|
|
45
48
|
const getSecuredInitialConfig = require('./lib/initialConfigValidation')
|
|
46
49
|
const override = require('./lib/pluginOverride')
|
|
47
50
|
const warning = require('./lib/warnings')
|
|
51
|
+
const noopSet = require('./lib/noop-set')
|
|
48
52
|
const { defaultInitOptions } = getSecuredInitialConfig
|
|
49
53
|
|
|
50
54
|
const {
|
|
51
55
|
FST_ERR_BAD_URL,
|
|
52
|
-
|
|
56
|
+
AVVIO_ERRORS_MAP,
|
|
57
|
+
appendStackTrace
|
|
53
58
|
} = require('./lib/errors')
|
|
54
59
|
|
|
60
|
+
const { buildErrorHandler } = require('./lib/error-handler.js')
|
|
61
|
+
|
|
55
62
|
const onBadUrlContext = {
|
|
56
63
|
config: {
|
|
57
64
|
},
|
|
58
65
|
onSend: [],
|
|
59
|
-
onError: []
|
|
66
|
+
onError: [],
|
|
67
|
+
[kFourOhFourContext]: null
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
function defaultBuildPrettyMeta (route) {
|
|
@@ -72,21 +80,6 @@ function defaultBuildPrettyMeta (route) {
|
|
|
72
80
|
return Object.assign({}, cleanKeys)
|
|
73
81
|
}
|
|
74
82
|
|
|
75
|
-
function defaultErrorHandler (error, request, reply) {
|
|
76
|
-
if (reply.statusCode < 500) {
|
|
77
|
-
reply.log.info(
|
|
78
|
-
{ res: reply, err: error },
|
|
79
|
-
error && error.message
|
|
80
|
-
)
|
|
81
|
-
} else {
|
|
82
|
-
reply.log.error(
|
|
83
|
-
{ req: request, res: reply, err: error },
|
|
84
|
-
error && error.message
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
reply.send(error)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
83
|
function fastify (options) {
|
|
91
84
|
// Options validations
|
|
92
85
|
options = options || {}
|
|
@@ -111,7 +104,6 @@ function fastify (options) {
|
|
|
111
104
|
const requestIdLogLabel = options.requestIdLogLabel || 'reqId'
|
|
112
105
|
const bodyLimit = options.bodyLimit || defaultInitOptions.bodyLimit
|
|
113
106
|
const disableRequestLogging = options.disableRequestLogging || false
|
|
114
|
-
const exposeHeadRoutes = options.exposeHeadRoutes != null ? options.exposeHeadRoutes : false
|
|
115
107
|
|
|
116
108
|
const ajvOptions = Object.assign({
|
|
117
109
|
customOptions: {},
|
|
@@ -133,6 +125,7 @@ function fastify (options) {
|
|
|
133
125
|
// Update the options with the fixed values
|
|
134
126
|
options.connectionTimeout = options.connectionTimeout || defaultInitOptions.connectionTimeout
|
|
135
127
|
options.keepAliveTimeout = options.keepAliveTimeout || defaultInitOptions.keepAliveTimeout
|
|
128
|
+
options.forceCloseConnections = typeof options.forceCloseConnections === 'boolean' ? options.forceCloseConnections : defaultInitOptions.forceCloseConnections
|
|
136
129
|
options.maxRequestsPerSocket = options.maxRequestsPerSocket || defaultInitOptions.maxRequestsPerSocket
|
|
137
130
|
options.requestTimeout = options.requestTimeout || defaultInitOptions.requestTimeout
|
|
138
131
|
options.logger = logger
|
|
@@ -143,9 +136,12 @@ function fastify (options) {
|
|
|
143
136
|
options.disableRequestLogging = disableRequestLogging
|
|
144
137
|
options.ajv = ajvOptions
|
|
145
138
|
options.clientErrorHandler = options.clientErrorHandler || defaultClientErrorHandler
|
|
146
|
-
options.exposeHeadRoutes = exposeHeadRoutes
|
|
147
139
|
|
|
148
140
|
const initialConfig = getSecuredInitialConfig(options)
|
|
141
|
+
const keepAliveConnections = options.forceCloseConnections === true ? new Set() : noopSet()
|
|
142
|
+
|
|
143
|
+
// exposeHeadRoutes have its defult set from the validatorfrom the validatorfrom the validatorfrom the validator
|
|
144
|
+
options.exposeHeadRoutes = initialConfig.exposeHeadRoutes
|
|
149
145
|
|
|
150
146
|
let constraints = options.constraints
|
|
151
147
|
if (options.versioning) {
|
|
@@ -169,14 +165,15 @@ function fastify (options) {
|
|
|
169
165
|
// Default router
|
|
170
166
|
const router = buildRouting({
|
|
171
167
|
config: {
|
|
172
|
-
defaultRoute
|
|
173
|
-
onBadUrl
|
|
174
|
-
constraints
|
|
168
|
+
defaultRoute,
|
|
169
|
+
onBadUrl,
|
|
170
|
+
constraints,
|
|
175
171
|
ignoreTrailingSlash: options.ignoreTrailingSlash || defaultInitOptions.ignoreTrailingSlash,
|
|
176
172
|
maxParamLength: options.maxParamLength || defaultInitOptions.maxParamLength,
|
|
177
173
|
caseSensitive: options.caseSensitive,
|
|
178
174
|
buildPrettyMeta: defaultBuildPrettyMeta
|
|
179
|
-
}
|
|
175
|
+
},
|
|
176
|
+
keepAliveConnections
|
|
180
177
|
})
|
|
181
178
|
|
|
182
179
|
// 404 router, used for handling encapsulated 404 handlers
|
|
@@ -200,8 +197,10 @@ function fastify (options) {
|
|
|
200
197
|
closing: false,
|
|
201
198
|
started: false
|
|
202
199
|
},
|
|
200
|
+
[kKeepAliveConnections]: keepAliveConnections,
|
|
203
201
|
[kOptions]: options,
|
|
204
202
|
[kChildren]: [],
|
|
203
|
+
[kServerBindings]: [],
|
|
205
204
|
[kBodyLimit]: bodyLimit,
|
|
206
205
|
[kRoutePrefix]: '',
|
|
207
206
|
[kLogLevel]: '',
|
|
@@ -209,7 +208,7 @@ function fastify (options) {
|
|
|
209
208
|
[kHooks]: new Hooks(),
|
|
210
209
|
[kSchemaController]: schemaController,
|
|
211
210
|
[kSchemaErrorFormatter]: null,
|
|
212
|
-
[kErrorHandler]:
|
|
211
|
+
[kErrorHandler]: buildErrorHandler(),
|
|
213
212
|
[kReplySerializerDefault]: null,
|
|
214
213
|
[kContentTypeParser]: new ContentTypeParser(
|
|
215
214
|
bodyLimit,
|
|
@@ -259,17 +258,19 @@ function fastify (options) {
|
|
|
259
258
|
},
|
|
260
259
|
// expose logger instance
|
|
261
260
|
log: logger,
|
|
261
|
+
// type provider
|
|
262
|
+
withTypeProvider,
|
|
262
263
|
// hooks
|
|
263
|
-
addHook
|
|
264
|
+
addHook,
|
|
264
265
|
// schemas
|
|
265
|
-
addSchema
|
|
266
|
+
addSchema,
|
|
266
267
|
getSchema: schemaController.getSchema.bind(schemaController),
|
|
267
268
|
getSchemas: schemaController.getSchemas.bind(schemaController),
|
|
268
|
-
setValidatorCompiler
|
|
269
|
-
setSerializerCompiler
|
|
270
|
-
setSchemaController
|
|
271
|
-
setReplySerializer
|
|
272
|
-
setSchemaErrorFormatter
|
|
269
|
+
setValidatorCompiler,
|
|
270
|
+
setSerializerCompiler,
|
|
271
|
+
setSchemaController,
|
|
272
|
+
setReplySerializer,
|
|
273
|
+
setSchemaErrorFormatter,
|
|
273
274
|
// custom parsers
|
|
274
275
|
addContentTypeParser: ContentTypeParser.helpers.addContentTypeParser,
|
|
275
276
|
hasContentTypeParser: ContentTypeParser.helpers.hasContentTypeParser,
|
|
@@ -285,8 +286,14 @@ function fastify (options) {
|
|
|
285
286
|
close: null,
|
|
286
287
|
printPlugins: null,
|
|
287
288
|
// http server
|
|
288
|
-
listen
|
|
289
|
-
server
|
|
289
|
+
listen,
|
|
290
|
+
server,
|
|
291
|
+
addresses: function () {
|
|
292
|
+
/* istanbul ignore next */
|
|
293
|
+
const binded = this[kServerBindings].map(b => b.address())
|
|
294
|
+
binded.push(this.server.address())
|
|
295
|
+
return binded.filter(adr => adr)
|
|
296
|
+
},
|
|
290
297
|
// extend fastify objects
|
|
291
298
|
decorate: decorator.add,
|
|
292
299
|
hasDecorator: decorator.exist,
|
|
@@ -295,19 +302,16 @@ function fastify (options) {
|
|
|
295
302
|
hasRequestDecorator: decorator.existRequest,
|
|
296
303
|
hasReplyDecorator: decorator.existReply,
|
|
297
304
|
// fake http injection
|
|
298
|
-
inject
|
|
305
|
+
inject,
|
|
299
306
|
// pretty print of the registered routes
|
|
300
307
|
printRoutes,
|
|
301
308
|
// custom error handling
|
|
302
|
-
setNotFoundHandler
|
|
303
|
-
setErrorHandler
|
|
309
|
+
setNotFoundHandler,
|
|
310
|
+
setErrorHandler,
|
|
304
311
|
// Set fastify initial configuration options read-only object
|
|
305
312
|
initialConfig
|
|
306
313
|
}
|
|
307
314
|
|
|
308
|
-
fastify[kReply].prototype.server = fastify
|
|
309
|
-
fastify[kRequest].prototype.server = fastify
|
|
310
|
-
|
|
311
315
|
Object.defineProperties(fastify, {
|
|
312
316
|
pluginName: {
|
|
313
317
|
get () {
|
|
@@ -331,16 +335,11 @@ function fastify (options) {
|
|
|
331
335
|
},
|
|
332
336
|
errorHandler: {
|
|
333
337
|
get () {
|
|
334
|
-
return this[kErrorHandler]
|
|
338
|
+
return this[kErrorHandler].func
|
|
335
339
|
}
|
|
336
340
|
}
|
|
337
341
|
})
|
|
338
342
|
|
|
339
|
-
// We are adding `use` to the fastify prototype so the user
|
|
340
|
-
// can still access it (and get the expected error), but `decorate`
|
|
341
|
-
// will not detect it, and allow the user to override it.
|
|
342
|
-
Object.setPrototypeOf(fastify, { use })
|
|
343
|
-
|
|
344
343
|
if (options.schemaErrorFormatter) {
|
|
345
344
|
validateSchemaErrorFormatter(options.schemaErrorFormatter)
|
|
346
345
|
fastify[kSchemaErrorFormatter] = options.schemaErrorFormatter.bind(fastify)
|
|
@@ -375,6 +374,15 @@ function fastify (options) {
|
|
|
375
374
|
if (fastify[kState].listening) {
|
|
376
375
|
// No new TCP connections are accepted
|
|
377
376
|
instance.server.close(done)
|
|
377
|
+
|
|
378
|
+
for (const conn of fastify[kKeepAliveConnections]) {
|
|
379
|
+
// We must invoke the destroy method instead of merely unreffing
|
|
380
|
+
// the sockets. If we only unref, then the callback passed to
|
|
381
|
+
// `fastify.close` will never be invoked; nor will any of the
|
|
382
|
+
// registered `onClose` hooks.
|
|
383
|
+
conn.destroy()
|
|
384
|
+
fastify[kKeepAliveConnections].delete(conn)
|
|
385
|
+
}
|
|
378
386
|
} else {
|
|
379
387
|
done(null)
|
|
380
388
|
}
|
|
@@ -483,6 +491,13 @@ function fastify (options) {
|
|
|
483
491
|
}
|
|
484
492
|
|
|
485
493
|
function manageErr (err) {
|
|
494
|
+
// If the error comes out of Avvio's Error codes
|
|
495
|
+
// We create a make and preserve the previous error
|
|
496
|
+
// as cause
|
|
497
|
+
err = err != null && AVVIO_ERRORS_MAP[err.code] != null
|
|
498
|
+
? appendStackTrace(err, new AVVIO_ERRORS_MAP[err.code](err.message))
|
|
499
|
+
: err
|
|
500
|
+
|
|
486
501
|
if (cb) {
|
|
487
502
|
if (err) {
|
|
488
503
|
cb(err)
|
|
@@ -498,15 +513,16 @@ function fastify (options) {
|
|
|
498
513
|
}
|
|
499
514
|
}
|
|
500
515
|
|
|
501
|
-
|
|
502
|
-
|
|
516
|
+
// Used exclusively in TypeScript contexts to enable auto type inference from JSON schema.
|
|
517
|
+
function withTypeProvider () {
|
|
518
|
+
return this
|
|
503
519
|
}
|
|
504
520
|
|
|
505
521
|
// wrapper that we expose to the user for hooks handling
|
|
506
522
|
function addHook (name, fn) {
|
|
507
523
|
throwIfAlreadyStarted('Cannot call "addHook" when fastify instance is already started!')
|
|
508
524
|
|
|
509
|
-
if (name === 'onSend' || name === 'preSerialization' || name === 'onError') {
|
|
525
|
+
if (name === 'onSend' || name === 'preSerialization' || name === 'onError' || name === 'preParsing') {
|
|
510
526
|
if (fn.constructor.name === 'AsyncFunction' && fn.length === 4) {
|
|
511
527
|
throw new Error('Async function has too many arguments. Async hooks should not use the \'done\' argument.')
|
|
512
528
|
}
|
|
@@ -514,7 +530,7 @@ function fastify (options) {
|
|
|
514
530
|
if (fn.constructor.name === 'AsyncFunction' && fn.length !== 0) {
|
|
515
531
|
throw new Error('Async function has too many arguments. Async hooks should not use the \'done\' argument.')
|
|
516
532
|
}
|
|
517
|
-
} else
|
|
533
|
+
} else {
|
|
518
534
|
if (fn.constructor.name === 'AsyncFunction' && fn.length === 3) {
|
|
519
535
|
throw new Error('Async function has too many arguments. Async hooks should not use the \'done\' argument.')
|
|
520
536
|
}
|
|
@@ -524,6 +540,9 @@ function fastify (options) {
|
|
|
524
540
|
this.onClose(fn)
|
|
525
541
|
} else if (name === 'onReady') {
|
|
526
542
|
this[kHooks].add(name, fn)
|
|
543
|
+
} else if (name === 'onRoute') {
|
|
544
|
+
this[kHooks].validate(name, fn)
|
|
545
|
+
this[kHooks].add(name, fn)
|
|
527
546
|
} else {
|
|
528
547
|
this.after((err, done) => {
|
|
529
548
|
_addHook.call(this, name, fn)
|
|
@@ -652,7 +671,7 @@ function fastify (options) {
|
|
|
652
671
|
function setErrorHandler (func) {
|
|
653
672
|
throwIfAlreadyStarted('Cannot call "setErrorHandler" when fastify instance is already started!')
|
|
654
673
|
|
|
655
|
-
this[kErrorHandler] = func.bind(this)
|
|
674
|
+
this[kErrorHandler] = buildErrorHandler(this[kErrorHandler], func.bind(this))
|
|
656
675
|
return this
|
|
657
676
|
}
|
|
658
677
|
|