node-fastify 5.8.3
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/.borp.yaml +3 -0
- package/.markdownlint-cli2.yaml +22 -0
- package/.prettierignore +1 -0
- package/GOVERNANCE.md +4 -0
- package/LICENSE +21 -0
- package/PROJECT_CHARTER.md +126 -0
- package/README.md +423 -0
- package/SECURITY.md +220 -0
- package/SPONSORS.md +24 -0
- package/build/build-error-serializer.js +35 -0
- package/build/build-validation.js +169 -0
- package/build/sync-version.js +11 -0
- package/docs/Guides/Benchmarking.md +60 -0
- package/docs/Guides/Database.md +321 -0
- package/docs/Guides/Delay-Accepting-Requests.md +608 -0
- package/docs/Guides/Detecting-When-Clients-Abort.md +172 -0
- package/docs/Guides/Ecosystem.md +726 -0
- package/docs/Guides/Fluent-Schema.md +127 -0
- package/docs/Guides/Getting-Started.md +620 -0
- package/docs/Guides/Index.md +43 -0
- package/docs/Guides/Migration-Guide-V3.md +287 -0
- package/docs/Guides/Migration-Guide-V4.md +267 -0
- package/docs/Guides/Migration-Guide-V5.md +727 -0
- package/docs/Guides/Plugins-Guide.md +520 -0
- package/docs/Guides/Prototype-Poisoning.md +383 -0
- package/docs/Guides/Recommendations.md +378 -0
- package/docs/Guides/Serverless.md +604 -0
- package/docs/Guides/Style-Guide.md +246 -0
- package/docs/Guides/Testing.md +481 -0
- package/docs/Guides/Write-Plugin.md +103 -0
- package/docs/Guides/Write-Type-Provider.md +34 -0
- package/docs/Reference/ContentTypeParser.md +271 -0
- package/docs/Reference/Decorators.md +436 -0
- package/docs/Reference/Encapsulation.md +194 -0
- package/docs/Reference/Errors.md +377 -0
- package/docs/Reference/HTTP2.md +94 -0
- package/docs/Reference/Hooks.md +958 -0
- package/docs/Reference/Index.md +73 -0
- package/docs/Reference/LTS.md +86 -0
- package/docs/Reference/Lifecycle.md +99 -0
- package/docs/Reference/Logging.md +268 -0
- package/docs/Reference/Middleware.md +79 -0
- package/docs/Reference/Plugins.md +245 -0
- package/docs/Reference/Principles.md +73 -0
- package/docs/Reference/Reply.md +1001 -0
- package/docs/Reference/Request.md +295 -0
- package/docs/Reference/Routes.md +802 -0
- package/docs/Reference/Server.md +2389 -0
- package/docs/Reference/Type-Providers.md +256 -0
- package/docs/Reference/TypeScript.md +1729 -0
- package/docs/Reference/Validation-and-Serialization.md +1130 -0
- package/docs/Reference/Warnings.md +58 -0
- package/docs/index.md +24 -0
- package/docs/resources/encapsulation_context.drawio +1 -0
- package/docs/resources/encapsulation_context.svg +3 -0
- package/eslint.config.js +35 -0
- package/examples/asyncawait.js +38 -0
- package/examples/benchmark/body.json +3 -0
- package/examples/benchmark/hooks-benchmark-async-await.js +44 -0
- package/examples/benchmark/hooks-benchmark.js +52 -0
- package/examples/benchmark/parser.js +47 -0
- package/examples/benchmark/simple.js +30 -0
- package/examples/benchmark/webstream.js +27 -0
- package/examples/hooks.js +91 -0
- package/examples/http2.js +39 -0
- package/examples/https.js +38 -0
- package/examples/parser.js +53 -0
- package/examples/plugin.js +12 -0
- package/examples/route-prefix.js +38 -0
- package/examples/shared-schema.js +38 -0
- package/examples/simple-stream.js +20 -0
- package/examples/simple.js +32 -0
- package/examples/simple.mjs +27 -0
- package/examples/typescript-server.ts +79 -0
- package/examples/use-plugin.js +29 -0
- package/fastify.d.ts +253 -0
- package/fastify.js +985 -0
- package/integration/server.js +29 -0
- package/integration/test.sh +23 -0
- package/lib/config-validator.js +1266 -0
- package/lib/content-type-parser.js +413 -0
- package/lib/content-type.js +160 -0
- package/lib/context.js +98 -0
- package/lib/decorate.js +152 -0
- package/lib/error-handler.js +173 -0
- package/lib/error-serializer.js +134 -0
- package/lib/error-status.js +14 -0
- package/lib/errors.js +516 -0
- package/lib/four-oh-four.js +190 -0
- package/lib/handle-request.js +195 -0
- package/lib/head-route.js +45 -0
- package/lib/hooks.js +429 -0
- package/lib/initial-config-validation.js +37 -0
- package/lib/logger-factory.js +136 -0
- package/lib/logger-pino.js +68 -0
- package/lib/noop-set.js +10 -0
- package/lib/plugin-override.js +90 -0
- package/lib/plugin-utils.js +169 -0
- package/lib/promise.js +23 -0
- package/lib/reply.js +1030 -0
- package/lib/req-id-gen-factory.js +52 -0
- package/lib/request.js +391 -0
- package/lib/route.js +686 -0
- package/lib/schema-controller.js +164 -0
- package/lib/schemas.js +207 -0
- package/lib/server.js +441 -0
- package/lib/symbols.js +71 -0
- package/lib/validation.js +280 -0
- package/lib/warnings.js +57 -0
- package/lib/wrap-thenable.js +84 -0
- package/package.json +225 -0
- package/scripts/validate-ecosystem-links.js +179 -0
- package/test/404s.test.js +2035 -0
- package/test/500s.test.js +422 -0
- package/test/allow-unsafe-regex.test.js +92 -0
- package/test/als.test.js +65 -0
- package/test/async-await.test.js +705 -0
- package/test/async-dispose.test.js +20 -0
- package/test/async_hooks.test.js +52 -0
- package/test/body-limit.test.js +224 -0
- package/test/buffer.test.js +74 -0
- package/test/build/error-serializer.test.js +36 -0
- package/test/build/version.test.js +14 -0
- package/test/build-certificate.js +109 -0
- package/test/bundler/README.md +29 -0
- package/test/bundler/esbuild/bundler-test.js +32 -0
- package/test/bundler/esbuild/package.json +10 -0
- package/test/bundler/esbuild/src/fail-plugin-version.js +14 -0
- package/test/bundler/esbuild/src/index.js +9 -0
- package/test/bundler/webpack/bundler-test.js +32 -0
- package/test/bundler/webpack/package.json +11 -0
- package/test/bundler/webpack/src/fail-plugin-version.js +14 -0
- package/test/bundler/webpack/src/index.js +9 -0
- package/test/bundler/webpack/webpack.config.js +15 -0
- package/test/case-insensitive.test.js +102 -0
- package/test/chainable.test.js +40 -0
- package/test/child-logger-factory.test.js +128 -0
- package/test/client-timeout.test.js +38 -0
- package/test/close-pipelining.test.js +78 -0
- package/test/close.test.js +706 -0
- package/test/conditional-pino.test.js +47 -0
- package/test/connection-timeout.test.js +42 -0
- package/test/constrained-routes.test.js +1138 -0
- package/test/content-length.test.js +174 -0
- package/test/content-parser.test.js +739 -0
- package/test/content-type.test.js +181 -0
- package/test/context-config.test.js +164 -0
- package/test/custom-http-server.test.js +118 -0
- package/test/custom-parser-async.test.js +59 -0
- package/test/custom-parser.0.test.js +701 -0
- package/test/custom-parser.1.test.js +266 -0
- package/test/custom-parser.2.test.js +91 -0
- package/test/custom-parser.3.test.js +208 -0
- package/test/custom-parser.4.test.js +218 -0
- package/test/custom-parser.5.test.js +130 -0
- package/test/custom-querystring-parser.test.js +129 -0
- package/test/decorator.test.js +1330 -0
- package/test/delete.test.js +344 -0
- package/test/diagnostics-channel/404.test.js +49 -0
- package/test/diagnostics-channel/async-delay-request.test.js +65 -0
- package/test/diagnostics-channel/async-request.test.js +64 -0
- package/test/diagnostics-channel/error-before-handler.test.js +35 -0
- package/test/diagnostics-channel/error-request.test.js +53 -0
- package/test/diagnostics-channel/error-status.test.js +123 -0
- package/test/diagnostics-channel/init.test.js +50 -0
- package/test/diagnostics-channel/sync-delay-request.test.js +49 -0
- package/test/diagnostics-channel/sync-request-reply.test.js +51 -0
- package/test/diagnostics-channel/sync-request.test.js +54 -0
- package/test/encapsulated-child-logger-factory.test.js +69 -0
- package/test/encapsulated-error-handler.test.js +237 -0
- package/test/esm/errorCodes.test.mjs +10 -0
- package/test/esm/esm.test.mjs +13 -0
- package/test/esm/index.test.js +8 -0
- package/test/esm/named-exports.mjs +14 -0
- package/test/esm/other.mjs +8 -0
- package/test/esm/plugin.mjs +8 -0
- package/test/fastify-instance.test.js +300 -0
- package/test/find-route.test.js +152 -0
- package/test/fluent-schema.test.js +209 -0
- package/test/genReqId.test.js +426 -0
- package/test/handler-context.test.js +45 -0
- package/test/handler-timeout.test.js +367 -0
- package/test/has-route.test.js +88 -0
- package/test/header-overflow.test.js +55 -0
- package/test/helper.js +496 -0
- package/test/hooks-async.test.js +1099 -0
- package/test/hooks.on-listen.test.js +1162 -0
- package/test/hooks.on-ready.test.js +421 -0
- package/test/hooks.test.js +3578 -0
- package/test/http-methods/copy.test.js +35 -0
- package/test/http-methods/custom-http-methods.test.js +114 -0
- package/test/http-methods/get.test.js +412 -0
- package/test/http-methods/head.test.js +263 -0
- package/test/http-methods/lock.test.js +108 -0
- package/test/http-methods/mkcalendar.test.js +143 -0
- package/test/http-methods/mkcol.test.js +35 -0
- package/test/http-methods/move.test.js +42 -0
- package/test/http-methods/propfind.test.js +136 -0
- package/test/http-methods/proppatch.test.js +105 -0
- package/test/http-methods/report.test.js +142 -0
- package/test/http-methods/search.test.js +233 -0
- package/test/http-methods/trace.test.js +21 -0
- package/test/http-methods/unlock.test.js +38 -0
- package/test/http2/closing.test.js +270 -0
- package/test/http2/constraint.test.js +109 -0
- package/test/http2/head.test.js +34 -0
- package/test/http2/plain.test.js +68 -0
- package/test/http2/secure-with-fallback.test.js +113 -0
- package/test/http2/secure.test.js +67 -0
- package/test/http2/unknown-http-method.test.js +34 -0
- package/test/https/custom-https-server.test.js +58 -0
- package/test/https/https.test.js +136 -0
- package/test/imports.test.js +17 -0
- package/test/inject.test.js +502 -0
- package/test/input-validation.js +335 -0
- package/test/internals/all.test.js +38 -0
- package/test/internals/content-type-parser.test.js +111 -0
- package/test/internals/context.test.js +31 -0
- package/test/internals/decorator.test.js +156 -0
- package/test/internals/errors.test.js +982 -0
- package/test/internals/handle-request.test.js +270 -0
- package/test/internals/hook-runner.test.js +449 -0
- package/test/internals/hooks.test.js +96 -0
- package/test/internals/initial-config.test.js +383 -0
- package/test/internals/logger.test.js +163 -0
- package/test/internals/plugin.test.js +170 -0
- package/test/internals/promise.test.js +63 -0
- package/test/internals/reply-serialize.test.js +714 -0
- package/test/internals/reply.test.js +1920 -0
- package/test/internals/req-id-gen-factory.test.js +133 -0
- package/test/internals/request-validate.test.js +1402 -0
- package/test/internals/request.test.js +506 -0
- package/test/internals/schema-controller-perf.test.js +40 -0
- package/test/internals/server.test.js +91 -0
- package/test/internals/validation.test.js +352 -0
- package/test/issue-4959.test.js +118 -0
- package/test/keep-alive-timeout.test.js +42 -0
- package/test/listen.1.test.js +154 -0
- package/test/listen.2.test.js +113 -0
- package/test/listen.3.test.js +83 -0
- package/test/listen.4.test.js +168 -0
- package/test/listen.5.test.js +122 -0
- package/test/logger/instantiation.test.js +341 -0
- package/test/logger/logger-test-utils.js +47 -0
- package/test/logger/logging.test.js +460 -0
- package/test/logger/options.test.js +579 -0
- package/test/logger/request.test.js +292 -0
- package/test/logger/response.test.js +183 -0
- package/test/logger/tap-parallel-not-ok +0 -0
- package/test/max-requests-per-socket.test.js +113 -0
- package/test/middleware.test.js +37 -0
- package/test/noop-set.test.js +19 -0
- package/test/nullable-validation.test.js +187 -0
- package/test/options.error-handler.test.js +5 -0
- package/test/options.test.js +5 -0
- package/test/output-validation.test.js +140 -0
- package/test/patch.error-handler.test.js +5 -0
- package/test/patch.test.js +5 -0
- package/test/plugin.1.test.js +230 -0
- package/test/plugin.2.test.js +314 -0
- package/test/plugin.3.test.js +287 -0
- package/test/plugin.4.test.js +504 -0
- package/test/plugin.helper.js +8 -0
- package/test/plugin.name.display.js +10 -0
- package/test/post-empty-body.test.js +38 -0
- package/test/pretty-print.test.js +366 -0
- package/test/promises.test.js +125 -0
- package/test/proto-poisoning.test.js +145 -0
- package/test/put.error-handler.test.js +5 -0
- package/test/put.test.js +5 -0
- package/test/register.test.js +184 -0
- package/test/reply-code.test.js +148 -0
- package/test/reply-early-hints.test.js +100 -0
- package/test/reply-error.test.js +815 -0
- package/test/reply-trailers.test.js +445 -0
- package/test/reply-web-stream-locked.test.js +37 -0
- package/test/request-error.test.js +624 -0
- package/test/request-header-host.test.js +339 -0
- package/test/request-id.test.js +118 -0
- package/test/request-timeout.test.js +53 -0
- package/test/route-hooks.test.js +635 -0
- package/test/route-prefix.test.js +904 -0
- package/test/route-shorthand.test.js +48 -0
- package/test/route.1.test.js +259 -0
- package/test/route.2.test.js +100 -0
- package/test/route.3.test.js +213 -0
- package/test/route.4.test.js +127 -0
- package/test/route.5.test.js +211 -0
- package/test/route.6.test.js +306 -0
- package/test/route.7.test.js +406 -0
- package/test/route.8.test.js +225 -0
- package/test/router-options.test.js +1108 -0
- package/test/same-shape.test.js +124 -0
- package/test/schema-examples.test.js +661 -0
- package/test/schema-feature.test.js +2198 -0
- package/test/schema-serialization.test.js +1171 -0
- package/test/schema-special-usage.test.js +1348 -0
- package/test/schema-validation.test.js +1572 -0
- package/test/scripts/validate-ecosystem-links.test.js +339 -0
- package/test/serialize-response.test.js +186 -0
- package/test/server.test.js +347 -0
- package/test/set-error-handler.test.js +69 -0
- package/test/skip-reply-send.test.js +317 -0
- package/test/stream-serializers.test.js +40 -0
- package/test/stream.1.test.js +94 -0
- package/test/stream.2.test.js +129 -0
- package/test/stream.3.test.js +198 -0
- package/test/stream.4.test.js +176 -0
- package/test/stream.5.test.js +188 -0
- package/test/sync-routes.test.js +32 -0
- package/test/throw.test.js +359 -0
- package/test/toolkit.js +63 -0
- package/test/trust-proxy.test.js +162 -0
- package/test/type-provider.test.js +22 -0
- package/test/types/content-type-parser.test-d.ts +72 -0
- package/test/types/decorate-request-reply.test-d.ts +18 -0
- package/test/types/dummy-plugin.ts +9 -0
- package/test/types/errors.test-d.ts +90 -0
- package/test/types/fastify.test-d.ts +352 -0
- package/test/types/hooks.test-d.ts +550 -0
- package/test/types/import.ts +2 -0
- package/test/types/instance.test-d.ts +588 -0
- package/test/types/logger.test-d.ts +277 -0
- package/test/types/plugin.test-d.ts +97 -0
- package/test/types/register.test-d.ts +237 -0
- package/test/types/reply.test-d.ts +254 -0
- package/test/types/request.test-d.ts +188 -0
- package/test/types/route.test-d.ts +553 -0
- package/test/types/schema.test-d.ts +135 -0
- package/test/types/serverFactory.test-d.ts +37 -0
- package/test/types/type-provider.test-d.ts +1213 -0
- package/test/types/using.test-d.ts +17 -0
- package/test/upgrade.test.js +52 -0
- package/test/url-rewriting.test.js +122 -0
- package/test/use-semicolon-delimiter.test.js +168 -0
- package/test/validation-error-handling.test.js +900 -0
- package/test/versioned-routes.test.js +603 -0
- package/test/web-api.test.js +616 -0
- package/test/wrap-thenable.test.js +30 -0
- package/types/content-type-parser.d.ts +75 -0
- package/types/context.d.ts +22 -0
- package/types/errors.d.ts +92 -0
- package/types/hooks.d.ts +875 -0
- package/types/instance.d.ts +609 -0
- package/types/logger.d.ts +107 -0
- package/types/plugin.d.ts +44 -0
- package/types/register.d.ts +42 -0
- package/types/reply.d.ts +81 -0
- package/types/request.d.ts +95 -0
- package/types/route.d.ts +199 -0
- package/types/schema.d.ts +61 -0
- package/types/server-factory.d.ts +19 -0
- package/types/type-provider.d.ts +130 -0
- package/types/utils.d.ts +98 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @callback GenerateRequestId
|
|
5
|
+
* @param {Object} req
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} [requestIdHeader]
|
|
11
|
+
* @param {GenerateRequestId} [optGenReqId]
|
|
12
|
+
* @returns {GenerateRequestId}
|
|
13
|
+
*/
|
|
14
|
+
function reqIdGenFactory (requestIdHeader, optGenReqId) {
|
|
15
|
+
const genReqId = optGenReqId || buildDefaultGenReqId()
|
|
16
|
+
|
|
17
|
+
if (requestIdHeader) {
|
|
18
|
+
return buildOptionalHeaderReqId(requestIdHeader, genReqId)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return genReqId
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getGenReqId (contextServer, req) {
|
|
25
|
+
return contextServer.genReqId(req)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildDefaultGenReqId () {
|
|
29
|
+
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).
|
|
30
|
+
// With this upper bound, if you'll be generating 1k ids/sec, you're going to hit it in ~25 days.
|
|
31
|
+
// This is very likely to happen in real-world applications, hence the limit is enforced.
|
|
32
|
+
// Growing beyond this value will make the id generation slower and cause a deopt.
|
|
33
|
+
// In the worst cases, it will become a float, losing accuracy.
|
|
34
|
+
const maxInt = 2147483647
|
|
35
|
+
|
|
36
|
+
let nextReqId = 0
|
|
37
|
+
return function defaultGenReqId () {
|
|
38
|
+
nextReqId = (nextReqId + 1) & maxInt
|
|
39
|
+
return `req-${nextReqId.toString(36)}`
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function buildOptionalHeaderReqId (requestIdHeader, genReqId) {
|
|
44
|
+
return function (req) {
|
|
45
|
+
return req.headers[requestIdHeader] || genReqId(req)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = {
|
|
50
|
+
getGenReqId,
|
|
51
|
+
reqIdGenFactory
|
|
52
|
+
}
|
package/lib/request.js
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const proxyAddr = require('@fastify/proxy-addr')
|
|
4
|
+
const {
|
|
5
|
+
kHasBeenDecorated,
|
|
6
|
+
kSchemaBody,
|
|
7
|
+
kSchemaHeaders,
|
|
8
|
+
kSchemaParams,
|
|
9
|
+
kSchemaQuerystring,
|
|
10
|
+
kSchemaController,
|
|
11
|
+
kOptions,
|
|
12
|
+
kRequestCacheValidateFns,
|
|
13
|
+
kRouteContext,
|
|
14
|
+
kRequestOriginalUrl,
|
|
15
|
+
kRequestSignal,
|
|
16
|
+
kOnAbort
|
|
17
|
+
} = require('./symbols')
|
|
18
|
+
const { FST_ERR_REQ_INVALID_VALIDATION_INVOCATION, FST_ERR_DEC_UNDECLARED } = require('./errors')
|
|
19
|
+
const decorators = require('./decorate')
|
|
20
|
+
|
|
21
|
+
const HTTP_PART_SYMBOL_MAP = {
|
|
22
|
+
body: kSchemaBody,
|
|
23
|
+
headers: kSchemaHeaders,
|
|
24
|
+
params: kSchemaParams,
|
|
25
|
+
querystring: kSchemaQuerystring,
|
|
26
|
+
query: kSchemaQuerystring
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function Request (id, params, req, query, log, context) {
|
|
30
|
+
this.id = id
|
|
31
|
+
this[kRouteContext] = context
|
|
32
|
+
this.params = params
|
|
33
|
+
this.raw = req
|
|
34
|
+
this.query = query
|
|
35
|
+
this.log = log
|
|
36
|
+
this.body = undefined
|
|
37
|
+
}
|
|
38
|
+
Request.props = []
|
|
39
|
+
|
|
40
|
+
function getTrustProxyFn (tp) {
|
|
41
|
+
if (typeof tp === 'function') {
|
|
42
|
+
return tp
|
|
43
|
+
}
|
|
44
|
+
if (tp === true) {
|
|
45
|
+
// Support trusting everything
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
if (typeof tp === 'number') {
|
|
49
|
+
// Support trusting hop count
|
|
50
|
+
return function (a, i) { return i < tp }
|
|
51
|
+
}
|
|
52
|
+
if (typeof tp === 'string') {
|
|
53
|
+
// Support comma-separated tps
|
|
54
|
+
const values = tp.split(',').map(it => it.trim())
|
|
55
|
+
return proxyAddr.compile(values)
|
|
56
|
+
}
|
|
57
|
+
return proxyAddr.compile(tp)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function buildRequest (R, trustProxy) {
|
|
61
|
+
if (trustProxy) {
|
|
62
|
+
return buildRequestWithTrustProxy(R, trustProxy)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return buildRegularRequest(R)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function buildRegularRequest (R) {
|
|
69
|
+
const props = R.props.slice()
|
|
70
|
+
function _Request (id, params, req, query, log, context) {
|
|
71
|
+
this.id = id
|
|
72
|
+
this[kRouteContext] = context
|
|
73
|
+
this.params = params
|
|
74
|
+
this.raw = req
|
|
75
|
+
this.query = query
|
|
76
|
+
this.log = log
|
|
77
|
+
this.body = undefined
|
|
78
|
+
|
|
79
|
+
let prop
|
|
80
|
+
for (let i = 0; i < props.length; i++) {
|
|
81
|
+
prop = props[i]
|
|
82
|
+
this[prop.key] = prop.value
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
Object.setPrototypeOf(_Request.prototype, R.prototype)
|
|
86
|
+
Object.setPrototypeOf(_Request, R)
|
|
87
|
+
_Request.props = props
|
|
88
|
+
_Request.parent = R
|
|
89
|
+
|
|
90
|
+
return _Request
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function getLastEntryInMultiHeaderValue (headerValue) {
|
|
94
|
+
// we use the last one if the header is set more than once
|
|
95
|
+
const lastIndex = headerValue.lastIndexOf(',')
|
|
96
|
+
return lastIndex === -1 ? headerValue.trim() : headerValue.slice(lastIndex + 1).trim()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function buildRequestWithTrustProxy (R, trustProxy) {
|
|
100
|
+
const _Request = buildRegularRequest(R)
|
|
101
|
+
const proxyFn = getTrustProxyFn(trustProxy)
|
|
102
|
+
|
|
103
|
+
// This is a more optimized version of decoration
|
|
104
|
+
_Request[kHasBeenDecorated] = true
|
|
105
|
+
|
|
106
|
+
Object.defineProperties(_Request.prototype, {
|
|
107
|
+
ip: {
|
|
108
|
+
get () {
|
|
109
|
+
const addrs = proxyAddr.all(this.raw, proxyFn)
|
|
110
|
+
return addrs[addrs.length - 1]
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
ips: {
|
|
114
|
+
get () {
|
|
115
|
+
return proxyAddr.all(this.raw, proxyFn)
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
host: {
|
|
119
|
+
get () {
|
|
120
|
+
if (this.ip !== undefined && this.headers['x-forwarded-host']) {
|
|
121
|
+
return getLastEntryInMultiHeaderValue(this.headers['x-forwarded-host'])
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The last fallback supports the following cases:
|
|
125
|
+
* 1. http.requireHostHeader === false
|
|
126
|
+
* 2. HTTP/1.0 without a Host Header
|
|
127
|
+
* 3. Headers schema that may remove the Host Header
|
|
128
|
+
*/
|
|
129
|
+
return this.headers.host ?? this.headers[':authority'] ?? ''
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
protocol: {
|
|
133
|
+
get () {
|
|
134
|
+
if (this.headers['x-forwarded-proto']) {
|
|
135
|
+
return getLastEntryInMultiHeaderValue(this.headers['x-forwarded-proto'])
|
|
136
|
+
}
|
|
137
|
+
if (this.socket) {
|
|
138
|
+
return this.socket.encrypted ? 'https' : 'http'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
return _Request
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function assertsRequestDecoration (request, name) {
|
|
148
|
+
if (!decorators.hasKey(request, name) && !decorators.exist(request, name)) {
|
|
149
|
+
throw new FST_ERR_DEC_UNDECLARED(name, 'request')
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
Object.defineProperties(Request.prototype, {
|
|
154
|
+
server: {
|
|
155
|
+
get () {
|
|
156
|
+
return this[kRouteContext].server
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
url: {
|
|
160
|
+
get () {
|
|
161
|
+
return this.raw.url
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
originalUrl: {
|
|
165
|
+
get () {
|
|
166
|
+
/* istanbul ignore else */
|
|
167
|
+
if (!this[kRequestOriginalUrl]) {
|
|
168
|
+
this[kRequestOriginalUrl] = this.raw.originalUrl || this.raw.url
|
|
169
|
+
}
|
|
170
|
+
return this[kRequestOriginalUrl]
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
method: {
|
|
174
|
+
get () {
|
|
175
|
+
return this.raw.method
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
routeOptions: {
|
|
179
|
+
get () {
|
|
180
|
+
const context = this[kRouteContext]
|
|
181
|
+
const routeLimit = context._parserOptions.limit
|
|
182
|
+
const serverLimit = context.server.initialConfig.bodyLimit
|
|
183
|
+
const version = context.server.hasConstraintStrategy('version') ? this.raw.headers['accept-version'] : undefined
|
|
184
|
+
const options = {
|
|
185
|
+
method: context.config?.method,
|
|
186
|
+
url: context.config?.url,
|
|
187
|
+
bodyLimit: (routeLimit || serverLimit),
|
|
188
|
+
handlerTimeout: context.handlerTimeout,
|
|
189
|
+
attachValidation: context.attachValidation,
|
|
190
|
+
logLevel: context.logLevel,
|
|
191
|
+
exposeHeadRoute: context.exposeHeadRoute,
|
|
192
|
+
prefixTrailingSlash: context.prefixTrailingSlash,
|
|
193
|
+
handler: context.handler,
|
|
194
|
+
config: context.config,
|
|
195
|
+
schema: context.schema,
|
|
196
|
+
version
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return options
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
is404: {
|
|
203
|
+
get () {
|
|
204
|
+
return this[kRouteContext].config?.url === undefined
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
socket: {
|
|
208
|
+
get () {
|
|
209
|
+
return this.raw.socket
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
signal: {
|
|
213
|
+
get () {
|
|
214
|
+
let ac = this[kRequestSignal]
|
|
215
|
+
if (ac) return ac.signal
|
|
216
|
+
ac = new AbortController()
|
|
217
|
+
this[kRequestSignal] = ac
|
|
218
|
+
const onAbort = () => {
|
|
219
|
+
if (!ac.signal.aborted) ac.abort()
|
|
220
|
+
}
|
|
221
|
+
this.raw.on('close', onAbort)
|
|
222
|
+
this[kOnAbort] = onAbort
|
|
223
|
+
return ac.signal
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
ip: {
|
|
227
|
+
get () {
|
|
228
|
+
if (this.socket) {
|
|
229
|
+
return this.socket.remoteAddress
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
host: {
|
|
234
|
+
get () {
|
|
235
|
+
/**
|
|
236
|
+
* The last fallback supports the following cases:
|
|
237
|
+
* 1. http.requireHostHeader === false
|
|
238
|
+
* 2. HTTP/1.0 without a Host Header
|
|
239
|
+
* 3. Headers schema that may remove the Host Header
|
|
240
|
+
*/
|
|
241
|
+
return this.raw.headers.host ?? this.raw.headers[':authority'] ?? ''
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
hostname: {
|
|
245
|
+
get () {
|
|
246
|
+
// Check for IPV6 Host
|
|
247
|
+
if (this.host[0] === '[') {
|
|
248
|
+
return this.host.slice(0, this.host.indexOf(']') + 1)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return this.host.split(':', 1)[0]
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
port: {
|
|
255
|
+
get () {
|
|
256
|
+
// first try taking port from host
|
|
257
|
+
const portFromHost = parseInt(this.host.split(':').slice(-1)[0])
|
|
258
|
+
if (!isNaN(portFromHost)) {
|
|
259
|
+
return portFromHost
|
|
260
|
+
}
|
|
261
|
+
// now fall back to port from host/:authority header
|
|
262
|
+
const host = (this.headers.host ?? this.headers[':authority'] ?? '')
|
|
263
|
+
const portFromHeader = parseInt(host.split(':').slice(-1)[0])
|
|
264
|
+
if (!isNaN(portFromHeader)) {
|
|
265
|
+
return portFromHeader
|
|
266
|
+
}
|
|
267
|
+
// fall back to null
|
|
268
|
+
return null
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
protocol: {
|
|
272
|
+
get () {
|
|
273
|
+
if (this.socket) {
|
|
274
|
+
return this.socket.encrypted ? 'https' : 'http'
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
headers: {
|
|
279
|
+
get () {
|
|
280
|
+
if (this.additionalHeaders) {
|
|
281
|
+
return Object.assign({}, this.raw.headers, this.additionalHeaders)
|
|
282
|
+
}
|
|
283
|
+
return this.raw.headers
|
|
284
|
+
},
|
|
285
|
+
set (headers) {
|
|
286
|
+
this.additionalHeaders = headers
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
getValidationFunction: {
|
|
290
|
+
value: function (httpPartOrSchema) {
|
|
291
|
+
if (typeof httpPartOrSchema === 'string') {
|
|
292
|
+
const symbol = HTTP_PART_SYMBOL_MAP[httpPartOrSchema]
|
|
293
|
+
return this[kRouteContext][symbol]
|
|
294
|
+
} else if (typeof httpPartOrSchema === 'object') {
|
|
295
|
+
return this[kRouteContext][kRequestCacheValidateFns]?.get(httpPartOrSchema)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
compileValidationSchema: {
|
|
300
|
+
value: function (schema, httpPart = null) {
|
|
301
|
+
const { method, url } = this
|
|
302
|
+
|
|
303
|
+
if (this[kRouteContext][kRequestCacheValidateFns]?.has(schema)) {
|
|
304
|
+
return this[kRouteContext][kRequestCacheValidateFns].get(schema)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const validatorCompiler = this[kRouteContext].validatorCompiler ||
|
|
308
|
+
this.server[kSchemaController].validatorCompiler ||
|
|
309
|
+
(
|
|
310
|
+
// We compile the schemas if no custom validatorCompiler is provided
|
|
311
|
+
// nor set
|
|
312
|
+
this.server[kSchemaController].setupValidator(this.server[kOptions]) ||
|
|
313
|
+
this.server[kSchemaController].validatorCompiler
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
const validateFn = validatorCompiler({
|
|
317
|
+
schema,
|
|
318
|
+
method,
|
|
319
|
+
url,
|
|
320
|
+
httpPart
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
// We create a WeakMap to compile the schema only once
|
|
324
|
+
// Its done lazily to avoid add overhead by creating the WeakMap
|
|
325
|
+
// if it is not used
|
|
326
|
+
// TODO: Explore a central cache for all the schemas shared across
|
|
327
|
+
// encapsulated contexts
|
|
328
|
+
if (this[kRouteContext][kRequestCacheValidateFns] == null) {
|
|
329
|
+
this[kRouteContext][kRequestCacheValidateFns] = new WeakMap()
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
this[kRouteContext][kRequestCacheValidateFns].set(schema, validateFn)
|
|
333
|
+
|
|
334
|
+
return validateFn
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
validateInput: {
|
|
338
|
+
value: function (input, schema, httpPart) {
|
|
339
|
+
httpPart = typeof schema === 'string' ? schema : httpPart
|
|
340
|
+
|
|
341
|
+
const symbol = (httpPart != null && typeof httpPart === 'string') && HTTP_PART_SYMBOL_MAP[httpPart]
|
|
342
|
+
let validate
|
|
343
|
+
|
|
344
|
+
if (symbol) {
|
|
345
|
+
// Validate using the HTTP Request Part schema
|
|
346
|
+
validate = this[kRouteContext][symbol]
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// We cannot compile if the schema is missed
|
|
350
|
+
if (validate == null && (schema == null ||
|
|
351
|
+
typeof schema !== 'object' ||
|
|
352
|
+
Array.isArray(schema))
|
|
353
|
+
) {
|
|
354
|
+
throw new FST_ERR_REQ_INVALID_VALIDATION_INVOCATION(httpPart)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (validate == null) {
|
|
358
|
+
if (this[kRouteContext][kRequestCacheValidateFns]?.has(schema)) {
|
|
359
|
+
validate = this[kRouteContext][kRequestCacheValidateFns].get(schema)
|
|
360
|
+
} else {
|
|
361
|
+
// We proceed to compile if there's no validate function yet
|
|
362
|
+
validate = this.compileValidationSchema(schema, httpPart)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return validate(input)
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
getDecorator: {
|
|
370
|
+
value: function (name) {
|
|
371
|
+
assertsRequestDecoration(this, name)
|
|
372
|
+
|
|
373
|
+
const decorator = this[name]
|
|
374
|
+
if (typeof decorator === 'function') {
|
|
375
|
+
return decorator.bind(this)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return decorator
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
setDecorator: {
|
|
382
|
+
value: function (name, value) {
|
|
383
|
+
assertsRequestDecoration(this, name)
|
|
384
|
+
|
|
385
|
+
this[name] = value
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
module.exports = Request
|
|
391
|
+
module.exports.buildRequest = buildRequest
|