fastify 5.0.0-alpha.2 → 5.0.0-alpha.4
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 +2 -2
- package/SPONSORS.md +2 -0
- package/build/build-validation.js +3 -15
- package/docs/Guides/Ecosystem.md +4 -0
- package/docs/Guides/Getting-Started.md +0 -2
- package/docs/Guides/Migration-Guide-V4.md +48 -0
- package/docs/Guides/Recommendations.md +8 -6
- package/docs/Reference/Errors.md +0 -2
- package/docs/Reference/Hooks.md +5 -9
- package/docs/Reference/Logging.md +1 -1
- package/docs/Reference/Reply.md +9 -11
- package/docs/Reference/Request.md +0 -11
- package/docs/Reference/Routes.md +4 -23
- package/docs/Reference/Server.md +30 -40
- package/docs/Reference/Type-Providers.md +2 -2
- package/docs/Reference/TypeScript.md +16 -18
- package/docs/Reference/Validation-and-Serialization.md +62 -27
- package/docs/Reference/Warnings.md +0 -26
- package/eslint.config.js +9 -25
- package/fastify.d.ts +10 -23
- package/fastify.js +60 -61
- package/lib/configValidator.js +130 -182
- package/lib/context.js +1 -22
- package/lib/decorate.js +2 -2
- package/lib/errors.js +0 -6
- package/lib/handleRequest.js +5 -5
- package/lib/reply.js +34 -74
- package/lib/request.js +0 -45
- package/lib/route.js +12 -27
- package/lib/schemas.js +27 -22
- package/lib/server.js +6 -11
- package/lib/symbols.js +1 -1
- package/lib/validation.js +27 -6
- package/lib/warnings.js +1 -92
- package/lib/wrapThenable.js +1 -1
- package/package.json +14 -15
- package/test/decorator.test.js +1 -1
- package/test/diagnostics-channel/404.test.js +1 -1
- package/test/diagnostics-channel/async-delay-request.test.js +1 -1
- package/test/diagnostics-channel/async-request.test.js +1 -1
- package/test/diagnostics-channel/error-before-handler.test.js +1 -1
- package/test/diagnostics-channel/error-request.test.js +1 -1
- package/test/diagnostics-channel/error-status.test.js +1 -1
- package/test/diagnostics-channel/init.test.js +2 -2
- package/test/diagnostics-channel/sync-delay-request.test.js +1 -1
- package/test/diagnostics-channel/sync-request-reply.test.js +1 -1
- package/test/diagnostics-channel/sync-request.test.js +1 -1
- package/test/{copy.test.js → http-methods/copy.test.js} +2 -1
- package/test/http-methods/custom-http-methods.test.js +111 -0
- package/test/{get.test.js → http-methods/get.test.js} +1 -1
- package/test/{head.test.js → http-methods/head.test.js} +7 -87
- package/test/{lock.test.js → http-methods/lock.test.js} +2 -1
- package/test/{mkcalendar.test.js → http-methods/mkcalendar.test.js} +2 -1
- package/test/{mkcol.test.js → http-methods/mkcol.test.js} +2 -1
- package/test/{move.test.js → http-methods/move.test.js} +2 -1
- package/test/{propfind.test.js → http-methods/propfind.test.js} +2 -1
- package/test/{proppatch.test.js → http-methods/proppatch.test.js} +2 -1
- package/test/{report.test.js → http-methods/report.test.js} +2 -1
- package/test/{search.test.js → http-methods/search.test.js} +2 -1
- package/test/{trace.test.js → http-methods/trace.test.js} +2 -1
- package/test/{unlock.test.js → http-methods/unlock.test.js} +2 -1
- package/test/internals/all.test.js +3 -3
- package/test/internals/decorator.test.js +2 -2
- package/test/internals/errors.test.js +7 -17
- package/test/internals/initialConfig.test.js +0 -31
- package/test/internals/reply-serialize.test.js +25 -10
- package/test/internals/reply.test.js +31 -153
- package/test/internals/request-validate.test.js +21 -12
- package/test/internals/request.test.js +1 -18
- package/test/internals/validation.test.js +49 -56
- package/test/listen.1.test.js +66 -14
- package/test/listen.5.test.js +11 -0
- package/test/reply-trailers.test.js +1 -32
- package/test/route-shorthand.test.js +3 -1
- package/test/route.3.test.js +4 -1
- package/test/route.7.test.js +2 -12
- package/test/route.8.test.js +34 -5
- package/test/router-options.test.js +6 -3
- package/test/schema-examples.test.js +15 -6
- package/test/schema-feature.test.js +178 -35
- package/test/schema-serialization.test.js +125 -21
- package/test/schema-validation.test.js +154 -3
- package/test/skip-reply-send.test.js +6 -6
- package/test/stream-serializers.test.js +37 -0
- package/test/throw.test.js +2 -14
- package/test/types/errors.test-d.ts +1 -2
- package/test/types/fastify.test-d.ts +23 -34
- package/test/types/hooks.test-d.ts +56 -56
- package/test/types/instance.test-d.ts +3 -3
- package/test/types/reply.test-d.ts +7 -8
- package/test/types/request.test-d.ts +2 -12
- package/test/types/route.test-d.ts +158 -158
- package/test/types/schema.test-d.ts +22 -5
- package/test/versioned-routes.test.js +0 -90
- package/test/web-api.test.js +75 -0
- package/types/errors.d.ts +78 -79
- package/types/hooks.d.ts +18 -18
- package/types/instance.d.ts +1 -1
- package/types/logger.d.ts +7 -7
- package/types/reply.d.ts +18 -22
- package/types/request.d.ts +8 -14
- package/types/route.d.ts +5 -6
- package/types/type-provider.d.ts +1 -1
- package/.tap/processinfo/09002e93-10ad-430c-bc86-c0576928b0ed.json +0 -241
- package/.tap/processinfo/ee66c5ab-635d-48b5-8be6-3dc3ceea5bfc.json +0 -268
- package/.tap/test-results/test/404s.test.js.tap +0 -623
- package/.tap/test-results/test/500s.test.js.tap +0 -64
- package/.tap/test-results/test/allowUnsafeRegex.test.js.tap +0 -36
- package/.tap/test-results/test/als.test.js.tap +0 -15
- package/.tap/test-results/test/async-await.test.js.tap +0 -184
- package/.tap/test-results/test/async-dispose.test.js.tap +0 -8
- package/.tap/test-results/test/async_hooks.test.js.tap +0 -10
- package/.tap/test-results/test/bodyLimit.test.js.tap +0 -48
- package/.tap/test-results/test/buffer.test.js.tap +0 -20
- package/.tap/test-results/test/build/error-serializer.test.js.tap +0 -12
- package/.tap/test-results/test/build/version.test.js.tap +0 -7
- package/.tap/test-results/test/case-insensitive.test.js.tap +0 -36
- package/.tap/test-results/test/chainable.test.js.tap +0 -17
- package/.tap/test-results/test/check.test.js.tap +0 -10
- package/.tap/test-results/test/childLoggerFactory.test.js.tap +0 -23
- package/.tap/test-results/test/client-timeout.test.js.tap +0 -7
- package/.tap/test-results/test/close-pipelining.test.js.tap +0 -15
- package/.tap/test-results/test/close.test.js.tap +0 -172
- package/.tap/test-results/test/connectionTimeout.test.js.tap +0 -12
- package/.tap/test-results/test/constrained-routes.test.js.tap +0 -173
- package/.tap/test-results/test/content-length.test.js.tap +0 -46
- package/.tap/test-results/test/content-parser.test.js.tap +0 -266
- package/.tap/test-results/test/content-type.test.js.tap +0 -14
- package/.tap/test-results/test/context-config.test.js.tap +0 -41
- package/.tap/test-results/test/copy.test.js.tap +0 -14
- package/.tap/test-results/test/custom-http-server.test.js.tap +0 -30
- package/.tap/test-results/test/custom-parser-async.test.js.tap +0 -21
- package/.tap/test-results/test/custom-parser.0.test.js.tap +0 -199
- package/.tap/test-results/test/custom-parser.1.test.js.tap +0 -90
- package/.tap/test-results/test/custom-parser.2.test.js.tap +0 -22
- package/.tap/test-results/test/custom-parser.3.test.js.tap +0 -53
- package/.tap/test-results/test/custom-parser.4.test.js.tap +0 -45
- package/.tap/test-results/test/custom-parser.5.test.js.tap +0 -41
- package/.tap/test-results/test/custom-querystring-parser.test.js.tap +0 -46
- package/.tap/test-results/test/decorator.test.js.tap +0 -465
- package/.tap/test-results/test/delete.test.js.tap +0 -110
- package/.tap/test-results/test/diagnostics-channel/404.test.js.tap +0 -15
- package/.tap/test-results/test/diagnostics-channel/async-delay-request.test.js.tap +0 -25
- package/.tap/test-results/test/diagnostics-channel/async-request.test.js.tap +0 -24
- package/.tap/test-results/test/diagnostics-channel/error-before-handler.test.js.tap +0 -9
- package/.tap/test-results/test/diagnostics-channel/error-request.test.js.tap +0 -20
- package/.tap/test-results/test/diagnostics-channel/error-status.test.js.tap +0 -10
- package/.tap/test-results/test/diagnostics-channel/init.test.js.tap +0 -14
- package/.tap/test-results/test/diagnostics-channel/sync-delay-request.test.js.tap +0 -16
- package/.tap/test-results/test/diagnostics-channel/sync-request-reply.test.js.tap +0 -16
- package/.tap/test-results/test/diagnostics-channel/sync-request.test.js.tap +0 -19
- package/.tap/test-results/test/encapsulated-child-logger-factory.test.js.tap +0 -18
- package/.tap/test-results/test/encapsulated-error-handler.test.js.tap +0 -243
- package/.tap/test-results/test/esm/errorCodes.test.mjs.tap +0 -9
- package/.tap/test-results/test/esm/esm.test.mjs.tap +0 -8
- package/.tap/test-results/test/esm/index.test.js.tap +0 -8
- package/.tap/test-results/test/fastify-instance.test.js.tap +0 -114
- package/.tap/test-results/test/findRoute.test.js.tap +0 -37
- package/.tap/test-results/test/fluent-schema.test.js.tap +0 -36
- package/.tap/test-results/test/genReqId.test.js.tap +0 -106
- package/.tap/test-results/test/get.test.js.tap +0 -151
- package/.tap/test-results/test/handler-context.test.js.tap +0 -19
- package/.tap/test-results/test/has-route.test.js.tap +0 -30
- package/.tap/test-results/test/head.test.js.tap +0 -130
- package/.tap/test-results/test/header-overflow.test.js.tap +0 -16
- package/.tap/test-results/test/hooks-async.test.js.tap +0 -286
- package/.tap/test-results/test/hooks.on-listen.test.js.tap +0 -311
- package/.tap/test-results/test/hooks.on-ready.test.js.tap +0 -151
- package/.tap/test-results/test/hooks.test.js.tap +0 -966
- package/.tap/test-results/test/http2/closing.test.js.tap +0 -35
- package/.tap/test-results/test/http2/constraint.test.js.tap +0 -32
- package/.tap/test-results/test/http2/head.test.js.tap +0 -9
- package/.tap/test-results/test/http2/missing-http2-module.test.js.tap +0 -8
- package/.tap/test-results/test/http2/plain.test.js.tap +0 -22
- package/.tap/test-results/test/http2/secure-with-fallback.test.js.tap +0 -40
- package/.tap/test-results/test/http2/secure.test.js.tap +0 -27
- package/.tap/test-results/test/http2/unknown-http-method.test.js.tap +0 -9
- package/.tap/test-results/test/https/custom-https-server.test.js.tap +0 -10
- package/.tap/test-results/test/https/https.test.js.tap +0 -45
- package/.tap/test-results/test/imports.test.js.tap +0 -14
- package/.tap/test-results/test/inject.test.js.tap +0 -165
- package/.tap/test-results/test/internals/all.test.js.tap +0 -42
- package/.tap/test-results/test/internals/contentTypeParser.test.js.tap +0 -14
- package/.tap/test-results/test/internals/context.test.js.tap +0 -14
- package/.tap/test-results/test/internals/decorator.test.js.tap +0 -51
- package/.tap/test-results/test/internals/errors.test.js.tap +0 -1212
- package/.tap/test-results/test/internals/handleRequest.test.js.tap +0 -69
- package/.tap/test-results/test/internals/hookRunner.test.js.tap +0 -143
- package/.tap/test-results/test/internals/hooks.test.js.tap +0 -45
- package/.tap/test-results/test/internals/initialConfig.test.js.tap +0 -125
- package/.tap/test-results/test/internals/logger.test.js.tap +0 -71
- package/.tap/test-results/test/internals/plugin.test.js.tap +0 -48
- package/.tap/test-results/test/internals/reply-serialize.test.js.tap +0 -166
- package/.tap/test-results/test/internals/reply.test.js.tap +0 -688
- package/.tap/test-results/test/internals/reqIdGenFactory.test.js.tap +0 -74
- package/.tap/test-results/test/internals/request-validate.test.js.tap +0 -384
- package/.tap/test-results/test/internals/request.test.js.tap +0 -163
- package/.tap/test-results/test/internals/server.test.js.tap +0 -30
- package/.tap/test-results/test/internals/validation.test.js.tap +0 -121
- package/.tap/test-results/test/keepAliveTimeout.test.js.tap +0 -12
- package/.tap/test-results/test/listen.1.test.js.tap +0 -31
- package/.tap/test-results/test/listen.2.test.js.tap +0 -46
- package/.tap/test-results/test/listen.3.test.js.tap +0 -25
- package/.tap/test-results/test/listen.4.test.js.tap +0 -51
- package/.tap/test-results/test/lock.test.js.tap +0 -29
- package/.tap/test-results/test/logger/instantiation.test.js.tap +0 -92
- package/.tap/test-results/test/logger/logging.test.js.tap +0 -117
- package/.tap/test-results/test/logger/options.test.js.tap +0 -165
- package/.tap/test-results/test/logger/request.test.js.tap +0 -82
- package/.tap/test-results/test/logger/response.test.js.tap +0 -38
- package/.tap/test-results/test/maxRequestsPerSocket.test.js.tap +0 -44
- package/.tap/test-results/test/method-missing.test.js.tap +0 -8
- package/.tap/test-results/test/middleware.test.js.tap +0 -17
- package/.tap/test-results/test/mkcalendar.test.js.tap +0 -43
- package/.tap/test-results/test/mkcol.test.js.tap +0 -14
- package/.tap/test-results/test/move.test.js.tap +0 -15
- package/.tap/test-results/test/noop-set.test.js.tap +0 -8
- package/.tap/test-results/test/nullable-validation.test.js.tap +0 -36
- package/.tap/test-results/test/options.error-handler.test.js.tap +0 -186
- package/.tap/test-results/test/options.test.js.tap +0 -174
- package/.tap/test-results/test/output-validation.test.js.tap +0 -66
- package/.tap/test-results/test/patch.error-handler.test.js.tap +0 -206
- package/.tap/test-results/test/patch.test.js.tap +0 -182
- package/.tap/test-results/test/plugin.1.test.js.tap +0 -78
- package/.tap/test-results/test/plugin.2.test.js.tap +0 -102
- package/.tap/test-results/test/plugin.3.test.js.tap +0 -58
- package/.tap/test-results/test/plugin.4.test.js.tap +0 -164
- package/.tap/test-results/test/post-empty-body.test.js.tap +0 -8
- package/.tap/test-results/test/pretty-print.test.js.tap +0 -82
- package/.tap/test-results/test/promises.test.js.tap +0 -46
- package/.tap/test-results/test/propfind.test.js.tap +0 -43
- package/.tap/test-results/test/proppatch.test.js.tap +0 -29
- package/.tap/test-results/test/proto-poisoning.test.js.tap +0 -47
- package/.tap/test-results/test/put.error-handler.test.js.tap +0 -206
- package/.tap/test-results/test/put.test.js.tap +0 -182
- package/.tap/test-results/test/register.test.js.tap +0 -61
- package/.tap/test-results/test/reply-code.test.js.tap +0 -40
- package/.tap/test-results/test/reply-earlyHints.test.js.tap +0 -22
- package/.tap/test-results/test/reply-error.test.js.tap +0 -643
- package/.tap/test-results/test/reply-trailers.test.js.tap +0 -176
- package/.tap/test-results/test/report.test.js.tap +0 -43
- package/.tap/test-results/test/request-error.test.js.tap +0 -98
- package/.tap/test-results/test/request-id.test.js.tap +0 -38
- package/.tap/test-results/test/request.deprecated.test.js.tap +0 -13
- package/.tap/test-results/test/requestTimeout.test.js.tap +0 -21
- package/.tap/test-results/test/route-hooks.test.js.tap +0 -498
- package/.tap/test-results/test/route-prefix.test.js.tap +0 -195
- package/.tap/test-results/test/route-shorthand.test.js.tap +0 -190
- package/.tap/test-results/test/route.1.test.js.tap +0 -93
- package/.tap/test-results/test/route.2.test.js.tap +0 -28
- package/.tap/test-results/test/route.3.test.js.tap +0 -39
- package/.tap/test-results/test/route.4.test.js.tap +0 -32
- package/.tap/test-results/test/route.5.test.js.tap +0 -54
- package/.tap/test-results/test/route.6.test.js.tap +0 -81
- package/.tap/test-results/test/route.7.test.js.tap +0 -93
- package/.tap/test-results/test/route.8.test.js.tap +0 -38
- package/.tap/test-results/test/router-options.test.js.tap +0 -104
- package/.tap/test-results/test/same-shape.test.js.tap +0 -22
- package/.tap/test-results/test/schema-examples.test.js.tap +0 -85
- package/.tap/test-results/test/schema-feature.test.js.tap +0 -445
- package/.tap/test-results/test/schema-serialization.test.js.tap +0 -194
- package/.tap/test-results/test/schema-special-usage.test.js.tap +0 -186
- package/.tap/test-results/test/schema-validation.test.js.tap +0 -199
- package/.tap/test-results/test/search.test.js.tap +0 -77
- package/.tap/test-results/test/serialize-response.test.js.tap +0 -26
- package/.tap/test-results/test/server.test.js.tap +0 -65
- package/.tap/test-results/test/set-error-handler.test.js.tap +0 -7
- package/.tap/test-results/test/skip-reply-send.test.js.tap +0 -272
- package/.tap/test-results/test/stream.1.test.js.tap +0 -36
- package/.tap/test-results/test/stream.2.test.js.tap +0 -20
- package/.tap/test-results/test/stream.3.test.js.tap +0 -34
- package/.tap/test-results/test/stream.4.test.js.tap +0 -40
- package/.tap/test-results/test/stream.5.test.js.tap +0 -37
- package/.tap/test-results/test/sync-routes.test.js.tap +0 -19
- package/.tap/test-results/test/throw.test.js.tap +0 -116
- package/.tap/test-results/test/trace.test.js.tap +0 -7
- package/.tap/test-results/test/trust-proxy.test.js.tap +0 -109
- package/.tap/test-results/test/type-provider.test.js.tap +0 -12
- package/.tap/test-results/test/unlock.test.js.tap +0 -14
- package/.tap/test-results/test/upgrade.test.js.tap +0 -8
- package/.tap/test-results/test/url-rewriting.test.js.tap +0 -39
- package/.tap/test-results/test/useSemicolonDelimiter.test.js.tap +0 -33
- package/.tap/test-results/test/validation-error-handling.test.js.tap +0 -180
- package/.tap/test-results/test/versioned-routes.test.js.tap +0 -151
- package/.tap/test-results/test/web-api.test.js.tap +0 -51
- package/.tap/test-results/test/wrapThenable.test.js.tap +0 -11
- package/EXPENSE_POLICY.md +0 -105
- package/lib/httpMethods.js +0 -40
- package/test/method-missing.test.js +0 -24
- package/test/request.deprecated.test.js +0 -38
package/lib/reply.js
CHANGED
|
@@ -5,7 +5,6 @@ const Readable = require('node:stream').Readable
|
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
7
|
kFourOhFourContext,
|
|
8
|
-
kPublicRouteContext,
|
|
9
8
|
kReplyErrorHandlerCalled,
|
|
10
9
|
kReplyHijacked,
|
|
11
10
|
kReplyStartTime,
|
|
@@ -47,7 +46,6 @@ const {
|
|
|
47
46
|
FST_ERR_REP_INVALID_PAYLOAD_TYPE,
|
|
48
47
|
FST_ERR_REP_RESPONSE_BODY_CONSUMED,
|
|
49
48
|
FST_ERR_REP_ALREADY_SENT,
|
|
50
|
-
FST_ERR_REP_SENT_VALUE,
|
|
51
49
|
FST_ERR_SEND_INSIDE_ONERR,
|
|
52
50
|
FST_ERR_BAD_STATUS_CODE,
|
|
53
51
|
FST_ERR_BAD_TRAILER_NAME,
|
|
@@ -55,7 +53,6 @@ const {
|
|
|
55
53
|
FST_ERR_MISSING_SERIALIZATION_FN,
|
|
56
54
|
FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN
|
|
57
55
|
} = require('./errors')
|
|
58
|
-
const { FSTDEP010, FSTDEP013, FSTDEP019, FSTDEP021 } = require('./warnings')
|
|
59
56
|
|
|
60
57
|
const toString = Object.prototype.toString
|
|
61
58
|
|
|
@@ -80,14 +77,6 @@ Object.defineProperties(Reply.prototype, {
|
|
|
80
77
|
return this.request[kRouteContext]
|
|
81
78
|
}
|
|
82
79
|
},
|
|
83
|
-
// TODO: remove once v5 is done
|
|
84
|
-
// Is temporary to avoid constant conflicts between `next` and `main`
|
|
85
|
-
context: {
|
|
86
|
-
get () {
|
|
87
|
-
FSTDEP019()
|
|
88
|
-
return this.request[kRouteContext]
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
80
|
elapsedTime: {
|
|
92
81
|
get () {
|
|
93
82
|
if (this[kReplyStartTime] === undefined) {
|
|
@@ -106,20 +95,6 @@ Object.defineProperties(Reply.prototype, {
|
|
|
106
95
|
get () {
|
|
107
96
|
// We are checking whether reply was hijacked or the response has ended.
|
|
108
97
|
return (this[kReplyHijacked] || this.raw.writableEnded) === true
|
|
109
|
-
},
|
|
110
|
-
set (value) {
|
|
111
|
-
FSTDEP010()
|
|
112
|
-
|
|
113
|
-
if (value !== true) {
|
|
114
|
-
throw new FST_ERR_REP_SENT_VALUE()
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// We throw only if sent was overwritten from Fastify
|
|
118
|
-
if (this.sent && this[kReplyHijacked]) {
|
|
119
|
-
throw new FST_ERR_REP_ALREADY_SENT(this.request.url, this.request.method)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this[kReplyHijacked] = true
|
|
123
98
|
}
|
|
124
99
|
},
|
|
125
100
|
statusCode: {
|
|
@@ -130,9 +105,9 @@ Object.defineProperties(Reply.prototype, {
|
|
|
130
105
|
this.code(value)
|
|
131
106
|
}
|
|
132
107
|
},
|
|
133
|
-
|
|
108
|
+
routeOptions: {
|
|
134
109
|
get () {
|
|
135
|
-
return this.request
|
|
110
|
+
return this.request.routeOptions
|
|
136
111
|
}
|
|
137
112
|
}
|
|
138
113
|
})
|
|
@@ -208,7 +183,7 @@ Reply.prototype.send = function (payload) {
|
|
|
208
183
|
payload = this[kReplySerializer](payload)
|
|
209
184
|
}
|
|
210
185
|
|
|
211
|
-
|
|
186
|
+
// The indexOf below also matches custom json mimetypes such as 'application/hal+json' or 'application/ld+json'
|
|
212
187
|
} else if (hasContentType === false || contentType.indexOf('json') > -1) {
|
|
213
188
|
if (hasContentType === false) {
|
|
214
189
|
this[kReplyHeaders]['content-type'] = CONTENT_TYPE.JSON
|
|
@@ -376,13 +351,13 @@ Reply.prototype.compileSerializationSchema = function (schema, httpStatus = null
|
|
|
376
351
|
}
|
|
377
352
|
|
|
378
353
|
const serializerCompiler = this[kRouteContext].serializerCompiler ||
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
354
|
+
this.server[kSchemaController].serializerCompiler ||
|
|
355
|
+
(
|
|
356
|
+
// We compile the schemas if no custom serializerCompiler is provided
|
|
357
|
+
// nor set
|
|
358
|
+
this.server[kSchemaController].setupSerializer(this.server[kOptions]) ||
|
|
359
|
+
this.server[kSchemaController].serializerCompiler
|
|
360
|
+
)
|
|
386
361
|
|
|
387
362
|
const serializeFn = serializerCompiler({
|
|
388
363
|
schema,
|
|
@@ -463,13 +438,6 @@ Reply.prototype.type = function (type) {
|
|
|
463
438
|
}
|
|
464
439
|
|
|
465
440
|
Reply.prototype.redirect = function (url, code) {
|
|
466
|
-
if (typeof url === 'number') {
|
|
467
|
-
FSTDEP021()
|
|
468
|
-
const temp = code
|
|
469
|
-
code = url
|
|
470
|
-
url = temp
|
|
471
|
-
}
|
|
472
|
-
|
|
473
441
|
if (!code) {
|
|
474
442
|
code = this[kReplyHasStatusCode] ? this.raw.statusCode : 302
|
|
475
443
|
}
|
|
@@ -600,14 +568,30 @@ function onSendEnd (reply, payload) {
|
|
|
600
568
|
reply.header('Trailer', header.trim())
|
|
601
569
|
}
|
|
602
570
|
|
|
603
|
-
// since Response contain status code,
|
|
604
|
-
//
|
|
605
|
-
|
|
606
|
-
if (
|
|
571
|
+
// since Response contain status code, headers and body,
|
|
572
|
+
// we need to update the status, add the headers and use it's body as payload
|
|
573
|
+
// before continuing
|
|
574
|
+
if (toString.call(payload) === '[object Response]') {
|
|
607
575
|
// https://developer.mozilla.org/en-US/docs/Web/API/Response/status
|
|
608
576
|
if (typeof payload.status === 'number') {
|
|
609
577
|
reply.code(payload.status)
|
|
610
578
|
}
|
|
579
|
+
|
|
580
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
|
|
581
|
+
if (typeof payload.headers === 'object' && typeof payload.headers.forEach === 'function') {
|
|
582
|
+
for (const [headerName, headerValue] of payload.headers) {
|
|
583
|
+
reply.header(headerName, headerValue)
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Response/body
|
|
588
|
+
if (payload.body !== null) {
|
|
589
|
+
if (payload.bodyUsed) {
|
|
590
|
+
throw new FST_ERR_REP_RESPONSE_BODY_CONSUMED()
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
// Keep going, body is either null or ReadableStream
|
|
594
|
+
payload = payload.body
|
|
611
595
|
}
|
|
612
596
|
const statusCode = res.statusCode
|
|
613
597
|
|
|
@@ -654,26 +638,6 @@ function onSendEnd (reply, payload) {
|
|
|
654
638
|
return
|
|
655
639
|
}
|
|
656
640
|
|
|
657
|
-
// Response
|
|
658
|
-
if (isResponse) {
|
|
659
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
|
|
660
|
-
if (typeof payload.headers === 'object' && typeof payload.headers.forEach === 'function') {
|
|
661
|
-
for (const [headerName, headerValue] of payload.headers) {
|
|
662
|
-
reply.header(headerName, headerValue)
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Response/body
|
|
667
|
-
if (payload.body != null) {
|
|
668
|
-
if (payload.bodyUsed) {
|
|
669
|
-
throw new FST_ERR_REP_RESPONSE_BODY_CONSUMED()
|
|
670
|
-
}
|
|
671
|
-
// Response.body always a ReadableStream
|
|
672
|
-
sendWebStream(payload.body, res, reply)
|
|
673
|
-
}
|
|
674
|
-
return
|
|
675
|
-
}
|
|
676
|
-
|
|
677
641
|
if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) {
|
|
678
642
|
throw new FST_ERR_REP_INVALID_PAYLOAD_TYPE(typeof payload)
|
|
679
643
|
}
|
|
@@ -681,9 +645,9 @@ function onSendEnd (reply, payload) {
|
|
|
681
645
|
if (reply[kReplyTrailers] === null) {
|
|
682
646
|
const contentLength = reply[kReplyHeaders]['content-length']
|
|
683
647
|
if (!contentLength ||
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
648
|
+
(req.raw.method !== 'HEAD' &&
|
|
649
|
+
Number(contentLength) !== Buffer.byteLength(payload)
|
|
650
|
+
)
|
|
687
651
|
) {
|
|
688
652
|
reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload)
|
|
689
653
|
}
|
|
@@ -724,7 +688,7 @@ function sendStream (payload, res, reply) {
|
|
|
724
688
|
if (res.headersSent || reply.request.raw.aborted === true) {
|
|
725
689
|
if (!errorLogged) {
|
|
726
690
|
errorLogged = true
|
|
727
|
-
logStreamError(reply.log, err,
|
|
691
|
+
logStreamError(reply.log, err, reply)
|
|
728
692
|
}
|
|
729
693
|
res.destroy()
|
|
730
694
|
} else {
|
|
@@ -812,10 +776,6 @@ function sendTrailer (payload, res, reply) {
|
|
|
812
776
|
const result = reply[kReplyTrailers][trailerName](reply, payload, cb)
|
|
813
777
|
if (typeof result === 'object' && typeof result.then === 'function') {
|
|
814
778
|
result.then((v) => cb(null, v), cb)
|
|
815
|
-
} else if (result !== null && result !== undefined) {
|
|
816
|
-
// TODO: should be removed in fastify@5
|
|
817
|
-
FSTDEP013()
|
|
818
|
-
cb(null, result)
|
|
819
779
|
}
|
|
820
780
|
}
|
|
821
781
|
|
package/lib/request.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const proxyAddr = require('proxy-addr')
|
|
4
|
-
const {
|
|
5
|
-
FSTDEP005,
|
|
6
|
-
FSTDEP012,
|
|
7
|
-
FSTDEP015,
|
|
8
|
-
FSTDEP016,
|
|
9
|
-
FSTDEP017,
|
|
10
|
-
FSTDEP018
|
|
11
|
-
} = require('./warnings')
|
|
12
4
|
const {
|
|
13
5
|
kHasBeenDecorated,
|
|
14
6
|
kSchemaBody,
|
|
@@ -19,7 +11,6 @@ const {
|
|
|
19
11
|
kOptions,
|
|
20
12
|
kRequestCacheValidateFns,
|
|
21
13
|
kRouteContext,
|
|
22
|
-
kPublicRouteContext,
|
|
23
14
|
kRequestOriginalUrl
|
|
24
15
|
} = require('./symbols')
|
|
25
16
|
const { FST_ERR_REQ_INVALID_VALIDATION_INVOCATION } = require('./errors')
|
|
@@ -171,18 +162,6 @@ Object.defineProperties(Request.prototype, {
|
|
|
171
162
|
return this.raw.method
|
|
172
163
|
}
|
|
173
164
|
},
|
|
174
|
-
context: {
|
|
175
|
-
get () {
|
|
176
|
-
FSTDEP012()
|
|
177
|
-
return this[kRouteContext]
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
routerPath: {
|
|
181
|
-
get () {
|
|
182
|
-
FSTDEP017()
|
|
183
|
-
return this[kRouteContext].config?.url
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
165
|
routeOptions: {
|
|
187
166
|
get () {
|
|
188
167
|
const context = this[kRouteContext]
|
|
@@ -213,35 +192,11 @@ Object.defineProperties(Request.prototype, {
|
|
|
213
192
|
return Object.freeze(options)
|
|
214
193
|
}
|
|
215
194
|
},
|
|
216
|
-
routerMethod: {
|
|
217
|
-
get () {
|
|
218
|
-
FSTDEP018()
|
|
219
|
-
return this[kRouteContext].config?.method
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
routeConfig: {
|
|
223
|
-
get () {
|
|
224
|
-
FSTDEP016()
|
|
225
|
-
return this[kRouteContext][kPublicRouteContext]?.config
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
routeSchema: {
|
|
229
|
-
get () {
|
|
230
|
-
FSTDEP015()
|
|
231
|
-
return this[kRouteContext][kPublicRouteContext].schema
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
195
|
is404: {
|
|
235
196
|
get () {
|
|
236
197
|
return this[kRouteContext].config?.url === undefined
|
|
237
198
|
}
|
|
238
199
|
},
|
|
239
|
-
connection: {
|
|
240
|
-
get () {
|
|
241
|
-
FSTDEP005()
|
|
242
|
-
return this.raw.connection
|
|
243
|
-
}
|
|
244
|
-
},
|
|
245
200
|
socket: {
|
|
246
201
|
get () {
|
|
247
202
|
return this.raw.socket
|
package/lib/route.js
CHANGED
|
@@ -4,13 +4,8 @@ const FindMyWay = require('find-my-way')
|
|
|
4
4
|
const Context = require('./context')
|
|
5
5
|
const handleRequest = require('./handleRequest')
|
|
6
6
|
const { onRequestAbortHookRunner, lifecycleHooks, preParsingHookRunner, onTimeoutHookRunner, onRequestHookRunner } = require('./hooks')
|
|
7
|
-
const { supportedMethods } = require('./httpMethods')
|
|
8
7
|
const { normalizeSchema } = require('./schemas')
|
|
9
8
|
const { parseHeadOnSendHandlers } = require('./headRoute')
|
|
10
|
-
const {
|
|
11
|
-
FSTDEP007,
|
|
12
|
-
FSTDEP008
|
|
13
|
-
} = require('./warnings')
|
|
14
9
|
|
|
15
10
|
const {
|
|
16
11
|
compileSchemasForValidation,
|
|
@@ -36,6 +31,7 @@ const {
|
|
|
36
31
|
|
|
37
32
|
const {
|
|
38
33
|
kRoutePrefix,
|
|
34
|
+
kSupportedHTTPMethods,
|
|
39
35
|
kLogLevel,
|
|
40
36
|
kLogSerializers,
|
|
41
37
|
kHooks,
|
|
@@ -91,7 +87,7 @@ function buildRouting (options) {
|
|
|
91
87
|
disableRequestLogging = options.disableRequestLogging
|
|
92
88
|
ignoreTrailingSlash = options.ignoreTrailingSlash
|
|
93
89
|
ignoreDuplicateSlashes = options.ignoreDuplicateSlashes
|
|
94
|
-
return503OnClosing = Object.
|
|
90
|
+
return503OnClosing = Object.hasOwn(options, 'return503OnClosing') ? options.return503OnClosing : true
|
|
95
91
|
keepAliveConnections = fastifyArgs.keepAliveConnections
|
|
96
92
|
},
|
|
97
93
|
routing: router.lookup.bind(router), // router func to find the right handler to call
|
|
@@ -207,12 +203,12 @@ function buildRouting (options) {
|
|
|
207
203
|
if (Array.isArray(opts.method)) {
|
|
208
204
|
// eslint-disable-next-line no-var
|
|
209
205
|
for (var i = 0; i < opts.method.length; ++i) {
|
|
210
|
-
opts.method[i] = normalizeAndValidateMethod(opts.method[i])
|
|
211
|
-
validateSchemaBodyOption(opts.method[i], path, opts.schema)
|
|
206
|
+
opts.method[i] = normalizeAndValidateMethod.call(this, opts.method[i])
|
|
207
|
+
validateSchemaBodyOption.call(this, opts.method[i], path, opts.schema)
|
|
212
208
|
}
|
|
213
209
|
} else {
|
|
214
|
-
opts.method = normalizeAndValidateMethod(opts.method)
|
|
215
|
-
validateSchemaBodyOption(opts.method, path, opts.schema)
|
|
210
|
+
opts.method = normalizeAndValidateMethod.call(this, opts.method)
|
|
211
|
+
validateSchemaBodyOption.call(this, opts.method, path, opts.schema)
|
|
216
212
|
}
|
|
217
213
|
|
|
218
214
|
if (!opts.handler) {
|
|
@@ -332,26 +328,16 @@ function buildRouting (options) {
|
|
|
332
328
|
isFastify
|
|
333
329
|
})
|
|
334
330
|
|
|
335
|
-
if (opts.version) {
|
|
336
|
-
FSTDEP008()
|
|
337
|
-
constraints.version = opts.version
|
|
338
|
-
}
|
|
339
|
-
|
|
340
331
|
const headHandler = router.findRoute('HEAD', opts.url, constraints)
|
|
341
332
|
const hasHEADHandler = headHandler !== null
|
|
342
333
|
|
|
343
|
-
// remove the head route created by fastify
|
|
344
|
-
if (isHeadRoute && hasHEADHandler && !context[kRouteByFastify] && headHandler.store[kRouteByFastify]) {
|
|
345
|
-
router.off('HEAD', opts.url, constraints)
|
|
346
|
-
}
|
|
347
|
-
|
|
348
334
|
try {
|
|
349
335
|
router.on(opts.method, opts.url, { constraints }, routeHandler, context)
|
|
350
336
|
} catch (error) {
|
|
351
337
|
// any route insertion error created by fastify can be safely ignore
|
|
352
338
|
// because it only duplicate route for head
|
|
353
339
|
if (!context[kRouteByFastify]) {
|
|
354
|
-
const isDuplicatedRoute = error.message.includes(`Method '${opts.method}' already declared for route
|
|
340
|
+
const isDuplicatedRoute = error.message.includes(`Method '${opts.method}' already declared for route`)
|
|
355
341
|
if (isDuplicatedRoute) {
|
|
356
342
|
throw new FST_ERR_DUPLICATED_ROUTE(opts.method, opts.url)
|
|
357
343
|
}
|
|
@@ -425,8 +411,6 @@ function buildRouting (options) {
|
|
|
425
411
|
if (shouldExposeHead && isGetRoute && !isHeadRoute && !hasHEADHandler) {
|
|
426
412
|
const onSendHandlers = parseHeadOnSendHandlers(headOpts.onSend)
|
|
427
413
|
prepareRoute.call(this, { method: 'HEAD', url: path, options: { ...headOpts, onSend: onSendHandlers }, isFastify: true })
|
|
428
|
-
} else if (hasHEADHandler && exposeHeadRoute) {
|
|
429
|
-
FSTDEP007()
|
|
430
414
|
}
|
|
431
415
|
}
|
|
432
416
|
}
|
|
@@ -549,7 +533,8 @@ function normalizeAndValidateMethod (method) {
|
|
|
549
533
|
throw new FST_ERR_ROUTE_METHOD_INVALID()
|
|
550
534
|
}
|
|
551
535
|
method = method.toUpperCase()
|
|
552
|
-
if (
|
|
536
|
+
if (!this[kSupportedHTTPMethods].bodyless.has(method) &&
|
|
537
|
+
!this[kSupportedHTTPMethods].bodywith.has(method)) {
|
|
553
538
|
throw new FST_ERR_ROUTE_METHOD_NOT_SUPPORTED(method)
|
|
554
539
|
}
|
|
555
540
|
|
|
@@ -557,7 +542,7 @@ function normalizeAndValidateMethod (method) {
|
|
|
557
542
|
}
|
|
558
543
|
|
|
559
544
|
function validateSchemaBodyOption (method, path, schema) {
|
|
560
|
-
if ((method
|
|
545
|
+
if (this[kSupportedHTTPMethods].bodyless.has(method) && schema?.body) {
|
|
561
546
|
throw new FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED(method, path)
|
|
562
547
|
}
|
|
563
548
|
}
|
|
@@ -580,9 +565,9 @@ function runPreParsing (err, request, reply) {
|
|
|
580
565
|
request[kRequestPayloadStream] = request.raw
|
|
581
566
|
|
|
582
567
|
if (request[kRouteContext].preParsing !== null) {
|
|
583
|
-
preParsingHookRunner(request[kRouteContext].preParsing, request, reply, handleRequest)
|
|
568
|
+
preParsingHookRunner(request[kRouteContext].preParsing, request, reply, handleRequest.bind(request.server))
|
|
584
569
|
} else {
|
|
585
|
-
handleRequest(null, request, reply)
|
|
570
|
+
handleRequest.call(request.server, null, request, reply)
|
|
586
571
|
}
|
|
587
572
|
}
|
|
588
573
|
|
package/lib/schemas.js
CHANGED
|
@@ -73,7 +73,18 @@ function normalizeSchema (routeSchemas, serverOptions) {
|
|
|
73
73
|
for (const key of SCHEMAS_SOURCE) {
|
|
74
74
|
const schema = routeSchemas[key]
|
|
75
75
|
if (schema && !isCustomSchemaPrototype(schema)) {
|
|
76
|
-
|
|
76
|
+
if (key === 'body' && schema.content) {
|
|
77
|
+
const contentProperty = schema.content
|
|
78
|
+
const keys = Object.keys(contentProperty)
|
|
79
|
+
for (let i = 0; i < keys.length; i++) {
|
|
80
|
+
const contentType = keys[i]
|
|
81
|
+
const contentSchema = contentProperty[contentType].schema
|
|
82
|
+
if (!contentSchema) {
|
|
83
|
+
throw new FST_ERR_SCH_CONTENT_MISSING_SCHEMA(contentType)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
77
88
|
}
|
|
78
89
|
}
|
|
79
90
|
|
|
@@ -86,25 +97,15 @@ function normalizeSchema (routeSchemas, serverOptions) {
|
|
|
86
97
|
|
|
87
98
|
const contentProperty = routeSchemas.response[code].content
|
|
88
99
|
|
|
89
|
-
let hasContentMultipleContentTypes = false
|
|
90
100
|
if (contentProperty) {
|
|
91
101
|
const keys = Object.keys(contentProperty)
|
|
92
102
|
for (let i = 0; i < keys.length; i++) {
|
|
93
103
|
const mediaName = keys[i]
|
|
94
104
|
if (!contentProperty[mediaName].schema) {
|
|
95
|
-
if (keys.length === 1) { break }
|
|
96
105
|
throw new FST_ERR_SCH_CONTENT_MISSING_SCHEMA(mediaName)
|
|
97
106
|
}
|
|
98
|
-
routeSchemas.response[code].content[mediaName].schema = getSchemaAnyway(contentProperty[mediaName].schema, serverOptions.jsonShorthand)
|
|
99
|
-
if (i === keys.length - 1) {
|
|
100
|
-
hasContentMultipleContentTypes = true
|
|
101
|
-
}
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
|
-
|
|
105
|
-
if (!hasContentMultipleContentTypes) {
|
|
106
|
-
routeSchemas.response[code] = getSchemaAnyway(routeSchemas.response[code], serverOptions.jsonShorthand)
|
|
107
|
-
}
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
|
|
@@ -129,17 +130,6 @@ function generateFluentSchema (schema) {
|
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
function getSchemaAnyway (schema, jsonShorthand) {
|
|
133
|
-
if (!jsonShorthand || schema.$ref || schema.oneOf || schema.allOf || schema.anyOf || schema.$merge || schema.$patch) return schema
|
|
134
|
-
if (!schema.type && !schema.properties) {
|
|
135
|
-
return {
|
|
136
|
-
type: 'object',
|
|
137
|
-
properties: schema
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return schema
|
|
141
|
-
}
|
|
142
|
-
|
|
143
133
|
/**
|
|
144
134
|
* Search for the right JSON schema compiled function in the request context
|
|
145
135
|
* setup by the route configuration `schema.response`.
|
|
@@ -163,6 +153,11 @@ function getSchemaSerializer (context, statusCode, contentType) {
|
|
|
163
153
|
return responseSchemaDef[statusCode][mediaName]
|
|
164
154
|
}
|
|
165
155
|
|
|
156
|
+
// fallback to match all media-type
|
|
157
|
+
if (responseSchemaDef[statusCode]['*/*']) {
|
|
158
|
+
return responseSchemaDef[statusCode]['*/*']
|
|
159
|
+
}
|
|
160
|
+
|
|
166
161
|
return false
|
|
167
162
|
}
|
|
168
163
|
return responseSchemaDef[statusCode]
|
|
@@ -175,6 +170,11 @@ function getSchemaSerializer (context, statusCode, contentType) {
|
|
|
175
170
|
return responseSchemaDef[fallbackStatusCode][mediaName]
|
|
176
171
|
}
|
|
177
172
|
|
|
173
|
+
// fallback to match all media-type
|
|
174
|
+
if (responseSchemaDef[fallbackStatusCode]['*/*']) {
|
|
175
|
+
return responseSchemaDef[fallbackStatusCode]['*/*']
|
|
176
|
+
}
|
|
177
|
+
|
|
178
178
|
return false
|
|
179
179
|
}
|
|
180
180
|
|
|
@@ -187,6 +187,11 @@ function getSchemaSerializer (context, statusCode, contentType) {
|
|
|
187
187
|
return responseSchemaDef.default[mediaName]
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
// fallback to match all media-type
|
|
191
|
+
if (responseSchemaDef.default['*/*']) {
|
|
192
|
+
return responseSchemaDef.default['*/*']
|
|
193
|
+
}
|
|
194
|
+
|
|
190
195
|
return false
|
|
191
196
|
}
|
|
192
197
|
|
package/lib/server.js
CHANGED
|
@@ -55,7 +55,8 @@ function createServer (options, httpHandler) {
|
|
|
55
55
|
} else {
|
|
56
56
|
host = listenOptions.host
|
|
57
57
|
}
|
|
58
|
-
if (Object.
|
|
58
|
+
if (!Object.hasOwn(listenOptions, 'host') ||
|
|
59
|
+
listenOptions.host == null) {
|
|
59
60
|
listenOptions.host = host
|
|
60
61
|
}
|
|
61
62
|
if (host === 'localhost') {
|
|
@@ -143,7 +144,6 @@ function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, o
|
|
|
143
144
|
cb: (_ignoreErr) => {
|
|
144
145
|
bound++
|
|
145
146
|
|
|
146
|
-
/* istanbul ignore next: the else won't be taken unless listening fails */
|
|
147
147
|
if (!_ignoreErr) {
|
|
148
148
|
this[kServerBindings].push(secondaryServer)
|
|
149
149
|
}
|
|
@@ -157,18 +157,13 @@ function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, o
|
|
|
157
157
|
|
|
158
158
|
const secondaryServer = getServerInstance(serverOpts, httpHandler)
|
|
159
159
|
const closeSecondary = () => {
|
|
160
|
-
// To avoid
|
|
160
|
+
// To avoid falling into situations where the close of the
|
|
161
161
|
// secondary server is triggered before the preClose hook
|
|
162
|
-
// is done running, we better wait until the main server
|
|
163
|
-
// is closed.
|
|
162
|
+
// is done running, we better wait until the main server is closed.
|
|
164
163
|
// No new TCP connections are accepted
|
|
165
|
-
// We swallow any error from the secondary
|
|
166
|
-
// server
|
|
164
|
+
// We swallow any error from the secondary server
|
|
167
165
|
secondaryServer.close(() => {})
|
|
168
|
-
if (serverOpts.forceCloseConnections ===
|
|
169
|
-
// Not needed in Node 19
|
|
170
|
-
secondaryServer.closeIdleConnections()
|
|
171
|
-
} else if (typeof secondaryServer.closeAllConnections === 'function' && serverOpts.forceCloseConnections) {
|
|
166
|
+
if (typeof secondaryServer.closeAllConnections === 'function' && serverOpts.forceCloseConnections === true) {
|
|
172
167
|
secondaryServer.closeAllConnections()
|
|
173
168
|
}
|
|
174
169
|
}
|
package/lib/symbols.js
CHANGED
|
@@ -5,6 +5,7 @@ const keys = {
|
|
|
5
5
|
kChildren: Symbol('fastify.children'),
|
|
6
6
|
kServerBindings: Symbol('fastify.serverBindings'),
|
|
7
7
|
kBodyLimit: Symbol('fastify.bodyLimit'),
|
|
8
|
+
kSupportedHTTPMethods: Symbol('fastify.acceptedHTTPMethods'),
|
|
8
9
|
kRoutePrefix: Symbol('fastify.routePrefix'),
|
|
9
10
|
kLogLevel: Symbol('fastify.logLevel'),
|
|
10
11
|
kLogSerializers: Symbol('fastify.logSerializers'),
|
|
@@ -15,7 +16,6 @@ const keys = {
|
|
|
15
16
|
kDisableRequestLogging: Symbol('fastify.disableRequestLogging'),
|
|
16
17
|
kPluginNameChain: Symbol('fastify.pluginNameChain'),
|
|
17
18
|
kRouteContext: Symbol('fastify.context'),
|
|
18
|
-
kPublicRouteContext: Symbol('fastify.routeOptions'),
|
|
19
19
|
kGenReqId: Symbol('fastify.genReqId'),
|
|
20
20
|
// Schema
|
|
21
21
|
kSchemaController: Symbol('fastify.schemaController'),
|
package/lib/validation.js
CHANGED
|
@@ -82,25 +82,35 @@ function compileSchemasForValidation (context, compile, isCustom) {
|
|
|
82
82
|
})
|
|
83
83
|
}
|
|
84
84
|
context[headersSchema] = compile({ schema: headersSchemaLowerCase, method, url, httpPart: 'headers' })
|
|
85
|
-
} else if (Object.
|
|
85
|
+
} else if (Object.hasOwn(schema, 'headers')) {
|
|
86
86
|
FSTWRN001('headers', method, url)
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
if (schema.body) {
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
const contentProperty = schema.body.content
|
|
91
|
+
if (contentProperty) {
|
|
92
|
+
const contentTypeSchemas = {}
|
|
93
|
+
for (const contentType of Object.keys(contentProperty)) {
|
|
94
|
+
const contentSchema = contentProperty[contentType].schema
|
|
95
|
+
contentTypeSchemas[contentType] = compile({ schema: contentSchema, method, url, httpPart: 'body', contentType })
|
|
96
|
+
}
|
|
97
|
+
context[bodySchema] = contentTypeSchemas
|
|
98
|
+
} else {
|
|
99
|
+
context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
|
|
100
|
+
}
|
|
101
|
+
} else if (Object.hasOwn(schema, 'body')) {
|
|
92
102
|
FSTWRN001('body', method, url)
|
|
93
103
|
}
|
|
94
104
|
|
|
95
105
|
if (schema.querystring) {
|
|
96
106
|
context[querystringSchema] = compile({ schema: schema.querystring, method, url, httpPart: 'querystring' })
|
|
97
|
-
} else if (Object.
|
|
107
|
+
} else if (Object.hasOwn(schema, 'querystring')) {
|
|
98
108
|
FSTWRN001('querystring', method, url)
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
if (schema.params) {
|
|
102
112
|
context[paramsSchema] = compile({ schema: schema.params, method, url, httpPart: 'params' })
|
|
103
|
-
} else if (Object.
|
|
113
|
+
} else if (Object.hasOwn(schema, 'params')) {
|
|
104
114
|
FSTWRN001('params', method, url)
|
|
105
115
|
}
|
|
106
116
|
}
|
|
@@ -140,7 +150,18 @@ function validate (context, request, execution) {
|
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
if (runExecution || !execution.skipBody) {
|
|
143
|
-
|
|
153
|
+
let validatorFunction = null
|
|
154
|
+
if (typeof context[bodySchema] === 'function') {
|
|
155
|
+
validatorFunction = context[bodySchema]
|
|
156
|
+
} else if (context[bodySchema]) {
|
|
157
|
+
// TODO: add request.contentType and reuse it here
|
|
158
|
+
const contentType = request.headers['content-type']?.split(';', 1)[0]
|
|
159
|
+
const contentSchema = context[bodySchema][contentType]
|
|
160
|
+
if (contentSchema) {
|
|
161
|
+
validatorFunction = contentSchema
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const body = validateParam(validatorFunction, request, 'body')
|
|
144
165
|
if (body) {
|
|
145
166
|
if (typeof body.then !== 'function') {
|
|
146
167
|
return wrapValidationError(body, 'body', context.schemaErrorFormatter)
|