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.
Files changed (354) hide show
  1. package/.borp.yaml +3 -0
  2. package/.markdownlint-cli2.yaml +22 -0
  3. package/.prettierignore +1 -0
  4. package/GOVERNANCE.md +4 -0
  5. package/LICENSE +21 -0
  6. package/PROJECT_CHARTER.md +126 -0
  7. package/README.md +423 -0
  8. package/SECURITY.md +220 -0
  9. package/SPONSORS.md +24 -0
  10. package/build/build-error-serializer.js +35 -0
  11. package/build/build-validation.js +169 -0
  12. package/build/sync-version.js +11 -0
  13. package/docs/Guides/Benchmarking.md +60 -0
  14. package/docs/Guides/Database.md +321 -0
  15. package/docs/Guides/Delay-Accepting-Requests.md +608 -0
  16. package/docs/Guides/Detecting-When-Clients-Abort.md +172 -0
  17. package/docs/Guides/Ecosystem.md +726 -0
  18. package/docs/Guides/Fluent-Schema.md +127 -0
  19. package/docs/Guides/Getting-Started.md +620 -0
  20. package/docs/Guides/Index.md +43 -0
  21. package/docs/Guides/Migration-Guide-V3.md +287 -0
  22. package/docs/Guides/Migration-Guide-V4.md +267 -0
  23. package/docs/Guides/Migration-Guide-V5.md +727 -0
  24. package/docs/Guides/Plugins-Guide.md +520 -0
  25. package/docs/Guides/Prototype-Poisoning.md +383 -0
  26. package/docs/Guides/Recommendations.md +378 -0
  27. package/docs/Guides/Serverless.md +604 -0
  28. package/docs/Guides/Style-Guide.md +246 -0
  29. package/docs/Guides/Testing.md +481 -0
  30. package/docs/Guides/Write-Plugin.md +103 -0
  31. package/docs/Guides/Write-Type-Provider.md +34 -0
  32. package/docs/Reference/ContentTypeParser.md +271 -0
  33. package/docs/Reference/Decorators.md +436 -0
  34. package/docs/Reference/Encapsulation.md +194 -0
  35. package/docs/Reference/Errors.md +377 -0
  36. package/docs/Reference/HTTP2.md +94 -0
  37. package/docs/Reference/Hooks.md +958 -0
  38. package/docs/Reference/Index.md +73 -0
  39. package/docs/Reference/LTS.md +86 -0
  40. package/docs/Reference/Lifecycle.md +99 -0
  41. package/docs/Reference/Logging.md +268 -0
  42. package/docs/Reference/Middleware.md +79 -0
  43. package/docs/Reference/Plugins.md +245 -0
  44. package/docs/Reference/Principles.md +73 -0
  45. package/docs/Reference/Reply.md +1001 -0
  46. package/docs/Reference/Request.md +295 -0
  47. package/docs/Reference/Routes.md +802 -0
  48. package/docs/Reference/Server.md +2389 -0
  49. package/docs/Reference/Type-Providers.md +256 -0
  50. package/docs/Reference/TypeScript.md +1729 -0
  51. package/docs/Reference/Validation-and-Serialization.md +1130 -0
  52. package/docs/Reference/Warnings.md +58 -0
  53. package/docs/index.md +24 -0
  54. package/docs/resources/encapsulation_context.drawio +1 -0
  55. package/docs/resources/encapsulation_context.svg +3 -0
  56. package/eslint.config.js +35 -0
  57. package/examples/asyncawait.js +38 -0
  58. package/examples/benchmark/body.json +3 -0
  59. package/examples/benchmark/hooks-benchmark-async-await.js +44 -0
  60. package/examples/benchmark/hooks-benchmark.js +52 -0
  61. package/examples/benchmark/parser.js +47 -0
  62. package/examples/benchmark/simple.js +30 -0
  63. package/examples/benchmark/webstream.js +27 -0
  64. package/examples/hooks.js +91 -0
  65. package/examples/http2.js +39 -0
  66. package/examples/https.js +38 -0
  67. package/examples/parser.js +53 -0
  68. package/examples/plugin.js +12 -0
  69. package/examples/route-prefix.js +38 -0
  70. package/examples/shared-schema.js +38 -0
  71. package/examples/simple-stream.js +20 -0
  72. package/examples/simple.js +32 -0
  73. package/examples/simple.mjs +27 -0
  74. package/examples/typescript-server.ts +79 -0
  75. package/examples/use-plugin.js +29 -0
  76. package/fastify.d.ts +253 -0
  77. package/fastify.js +985 -0
  78. package/integration/server.js +29 -0
  79. package/integration/test.sh +23 -0
  80. package/lib/config-validator.js +1266 -0
  81. package/lib/content-type-parser.js +413 -0
  82. package/lib/content-type.js +160 -0
  83. package/lib/context.js +98 -0
  84. package/lib/decorate.js +152 -0
  85. package/lib/error-handler.js +173 -0
  86. package/lib/error-serializer.js +134 -0
  87. package/lib/error-status.js +14 -0
  88. package/lib/errors.js +516 -0
  89. package/lib/four-oh-four.js +190 -0
  90. package/lib/handle-request.js +195 -0
  91. package/lib/head-route.js +45 -0
  92. package/lib/hooks.js +429 -0
  93. package/lib/initial-config-validation.js +37 -0
  94. package/lib/logger-factory.js +136 -0
  95. package/lib/logger-pino.js +68 -0
  96. package/lib/noop-set.js +10 -0
  97. package/lib/plugin-override.js +90 -0
  98. package/lib/plugin-utils.js +169 -0
  99. package/lib/promise.js +23 -0
  100. package/lib/reply.js +1030 -0
  101. package/lib/req-id-gen-factory.js +52 -0
  102. package/lib/request.js +391 -0
  103. package/lib/route.js +686 -0
  104. package/lib/schema-controller.js +164 -0
  105. package/lib/schemas.js +207 -0
  106. package/lib/server.js +441 -0
  107. package/lib/symbols.js +71 -0
  108. package/lib/validation.js +280 -0
  109. package/lib/warnings.js +57 -0
  110. package/lib/wrap-thenable.js +84 -0
  111. package/package.json +225 -0
  112. package/scripts/validate-ecosystem-links.js +179 -0
  113. package/test/404s.test.js +2035 -0
  114. package/test/500s.test.js +422 -0
  115. package/test/allow-unsafe-regex.test.js +92 -0
  116. package/test/als.test.js +65 -0
  117. package/test/async-await.test.js +705 -0
  118. package/test/async-dispose.test.js +20 -0
  119. package/test/async_hooks.test.js +52 -0
  120. package/test/body-limit.test.js +224 -0
  121. package/test/buffer.test.js +74 -0
  122. package/test/build/error-serializer.test.js +36 -0
  123. package/test/build/version.test.js +14 -0
  124. package/test/build-certificate.js +109 -0
  125. package/test/bundler/README.md +29 -0
  126. package/test/bundler/esbuild/bundler-test.js +32 -0
  127. package/test/bundler/esbuild/package.json +10 -0
  128. package/test/bundler/esbuild/src/fail-plugin-version.js +14 -0
  129. package/test/bundler/esbuild/src/index.js +9 -0
  130. package/test/bundler/webpack/bundler-test.js +32 -0
  131. package/test/bundler/webpack/package.json +11 -0
  132. package/test/bundler/webpack/src/fail-plugin-version.js +14 -0
  133. package/test/bundler/webpack/src/index.js +9 -0
  134. package/test/bundler/webpack/webpack.config.js +15 -0
  135. package/test/case-insensitive.test.js +102 -0
  136. package/test/chainable.test.js +40 -0
  137. package/test/child-logger-factory.test.js +128 -0
  138. package/test/client-timeout.test.js +38 -0
  139. package/test/close-pipelining.test.js +78 -0
  140. package/test/close.test.js +706 -0
  141. package/test/conditional-pino.test.js +47 -0
  142. package/test/connection-timeout.test.js +42 -0
  143. package/test/constrained-routes.test.js +1138 -0
  144. package/test/content-length.test.js +174 -0
  145. package/test/content-parser.test.js +739 -0
  146. package/test/content-type.test.js +181 -0
  147. package/test/context-config.test.js +164 -0
  148. package/test/custom-http-server.test.js +118 -0
  149. package/test/custom-parser-async.test.js +59 -0
  150. package/test/custom-parser.0.test.js +701 -0
  151. package/test/custom-parser.1.test.js +266 -0
  152. package/test/custom-parser.2.test.js +91 -0
  153. package/test/custom-parser.3.test.js +208 -0
  154. package/test/custom-parser.4.test.js +218 -0
  155. package/test/custom-parser.5.test.js +130 -0
  156. package/test/custom-querystring-parser.test.js +129 -0
  157. package/test/decorator.test.js +1330 -0
  158. package/test/delete.test.js +344 -0
  159. package/test/diagnostics-channel/404.test.js +49 -0
  160. package/test/diagnostics-channel/async-delay-request.test.js +65 -0
  161. package/test/diagnostics-channel/async-request.test.js +64 -0
  162. package/test/diagnostics-channel/error-before-handler.test.js +35 -0
  163. package/test/diagnostics-channel/error-request.test.js +53 -0
  164. package/test/diagnostics-channel/error-status.test.js +123 -0
  165. package/test/diagnostics-channel/init.test.js +50 -0
  166. package/test/diagnostics-channel/sync-delay-request.test.js +49 -0
  167. package/test/diagnostics-channel/sync-request-reply.test.js +51 -0
  168. package/test/diagnostics-channel/sync-request.test.js +54 -0
  169. package/test/encapsulated-child-logger-factory.test.js +69 -0
  170. package/test/encapsulated-error-handler.test.js +237 -0
  171. package/test/esm/errorCodes.test.mjs +10 -0
  172. package/test/esm/esm.test.mjs +13 -0
  173. package/test/esm/index.test.js +8 -0
  174. package/test/esm/named-exports.mjs +14 -0
  175. package/test/esm/other.mjs +8 -0
  176. package/test/esm/plugin.mjs +8 -0
  177. package/test/fastify-instance.test.js +300 -0
  178. package/test/find-route.test.js +152 -0
  179. package/test/fluent-schema.test.js +209 -0
  180. package/test/genReqId.test.js +426 -0
  181. package/test/handler-context.test.js +45 -0
  182. package/test/handler-timeout.test.js +367 -0
  183. package/test/has-route.test.js +88 -0
  184. package/test/header-overflow.test.js +55 -0
  185. package/test/helper.js +496 -0
  186. package/test/hooks-async.test.js +1099 -0
  187. package/test/hooks.on-listen.test.js +1162 -0
  188. package/test/hooks.on-ready.test.js +421 -0
  189. package/test/hooks.test.js +3578 -0
  190. package/test/http-methods/copy.test.js +35 -0
  191. package/test/http-methods/custom-http-methods.test.js +114 -0
  192. package/test/http-methods/get.test.js +412 -0
  193. package/test/http-methods/head.test.js +263 -0
  194. package/test/http-methods/lock.test.js +108 -0
  195. package/test/http-methods/mkcalendar.test.js +143 -0
  196. package/test/http-methods/mkcol.test.js +35 -0
  197. package/test/http-methods/move.test.js +42 -0
  198. package/test/http-methods/propfind.test.js +136 -0
  199. package/test/http-methods/proppatch.test.js +105 -0
  200. package/test/http-methods/report.test.js +142 -0
  201. package/test/http-methods/search.test.js +233 -0
  202. package/test/http-methods/trace.test.js +21 -0
  203. package/test/http-methods/unlock.test.js +38 -0
  204. package/test/http2/closing.test.js +270 -0
  205. package/test/http2/constraint.test.js +109 -0
  206. package/test/http2/head.test.js +34 -0
  207. package/test/http2/plain.test.js +68 -0
  208. package/test/http2/secure-with-fallback.test.js +113 -0
  209. package/test/http2/secure.test.js +67 -0
  210. package/test/http2/unknown-http-method.test.js +34 -0
  211. package/test/https/custom-https-server.test.js +58 -0
  212. package/test/https/https.test.js +136 -0
  213. package/test/imports.test.js +17 -0
  214. package/test/inject.test.js +502 -0
  215. package/test/input-validation.js +335 -0
  216. package/test/internals/all.test.js +38 -0
  217. package/test/internals/content-type-parser.test.js +111 -0
  218. package/test/internals/context.test.js +31 -0
  219. package/test/internals/decorator.test.js +156 -0
  220. package/test/internals/errors.test.js +982 -0
  221. package/test/internals/handle-request.test.js +270 -0
  222. package/test/internals/hook-runner.test.js +449 -0
  223. package/test/internals/hooks.test.js +96 -0
  224. package/test/internals/initial-config.test.js +383 -0
  225. package/test/internals/logger.test.js +163 -0
  226. package/test/internals/plugin.test.js +170 -0
  227. package/test/internals/promise.test.js +63 -0
  228. package/test/internals/reply-serialize.test.js +714 -0
  229. package/test/internals/reply.test.js +1920 -0
  230. package/test/internals/req-id-gen-factory.test.js +133 -0
  231. package/test/internals/request-validate.test.js +1402 -0
  232. package/test/internals/request.test.js +506 -0
  233. package/test/internals/schema-controller-perf.test.js +40 -0
  234. package/test/internals/server.test.js +91 -0
  235. package/test/internals/validation.test.js +352 -0
  236. package/test/issue-4959.test.js +118 -0
  237. package/test/keep-alive-timeout.test.js +42 -0
  238. package/test/listen.1.test.js +154 -0
  239. package/test/listen.2.test.js +113 -0
  240. package/test/listen.3.test.js +83 -0
  241. package/test/listen.4.test.js +168 -0
  242. package/test/listen.5.test.js +122 -0
  243. package/test/logger/instantiation.test.js +341 -0
  244. package/test/logger/logger-test-utils.js +47 -0
  245. package/test/logger/logging.test.js +460 -0
  246. package/test/logger/options.test.js +579 -0
  247. package/test/logger/request.test.js +292 -0
  248. package/test/logger/response.test.js +183 -0
  249. package/test/logger/tap-parallel-not-ok +0 -0
  250. package/test/max-requests-per-socket.test.js +113 -0
  251. package/test/middleware.test.js +37 -0
  252. package/test/noop-set.test.js +19 -0
  253. package/test/nullable-validation.test.js +187 -0
  254. package/test/options.error-handler.test.js +5 -0
  255. package/test/options.test.js +5 -0
  256. package/test/output-validation.test.js +140 -0
  257. package/test/patch.error-handler.test.js +5 -0
  258. package/test/patch.test.js +5 -0
  259. package/test/plugin.1.test.js +230 -0
  260. package/test/plugin.2.test.js +314 -0
  261. package/test/plugin.3.test.js +287 -0
  262. package/test/plugin.4.test.js +504 -0
  263. package/test/plugin.helper.js +8 -0
  264. package/test/plugin.name.display.js +10 -0
  265. package/test/post-empty-body.test.js +38 -0
  266. package/test/pretty-print.test.js +366 -0
  267. package/test/promises.test.js +125 -0
  268. package/test/proto-poisoning.test.js +145 -0
  269. package/test/put.error-handler.test.js +5 -0
  270. package/test/put.test.js +5 -0
  271. package/test/register.test.js +184 -0
  272. package/test/reply-code.test.js +148 -0
  273. package/test/reply-early-hints.test.js +100 -0
  274. package/test/reply-error.test.js +815 -0
  275. package/test/reply-trailers.test.js +445 -0
  276. package/test/reply-web-stream-locked.test.js +37 -0
  277. package/test/request-error.test.js +624 -0
  278. package/test/request-header-host.test.js +339 -0
  279. package/test/request-id.test.js +118 -0
  280. package/test/request-timeout.test.js +53 -0
  281. package/test/route-hooks.test.js +635 -0
  282. package/test/route-prefix.test.js +904 -0
  283. package/test/route-shorthand.test.js +48 -0
  284. package/test/route.1.test.js +259 -0
  285. package/test/route.2.test.js +100 -0
  286. package/test/route.3.test.js +213 -0
  287. package/test/route.4.test.js +127 -0
  288. package/test/route.5.test.js +211 -0
  289. package/test/route.6.test.js +306 -0
  290. package/test/route.7.test.js +406 -0
  291. package/test/route.8.test.js +225 -0
  292. package/test/router-options.test.js +1108 -0
  293. package/test/same-shape.test.js +124 -0
  294. package/test/schema-examples.test.js +661 -0
  295. package/test/schema-feature.test.js +2198 -0
  296. package/test/schema-serialization.test.js +1171 -0
  297. package/test/schema-special-usage.test.js +1348 -0
  298. package/test/schema-validation.test.js +1572 -0
  299. package/test/scripts/validate-ecosystem-links.test.js +339 -0
  300. package/test/serialize-response.test.js +186 -0
  301. package/test/server.test.js +347 -0
  302. package/test/set-error-handler.test.js +69 -0
  303. package/test/skip-reply-send.test.js +317 -0
  304. package/test/stream-serializers.test.js +40 -0
  305. package/test/stream.1.test.js +94 -0
  306. package/test/stream.2.test.js +129 -0
  307. package/test/stream.3.test.js +198 -0
  308. package/test/stream.4.test.js +176 -0
  309. package/test/stream.5.test.js +188 -0
  310. package/test/sync-routes.test.js +32 -0
  311. package/test/throw.test.js +359 -0
  312. package/test/toolkit.js +63 -0
  313. package/test/trust-proxy.test.js +162 -0
  314. package/test/type-provider.test.js +22 -0
  315. package/test/types/content-type-parser.test-d.ts +72 -0
  316. package/test/types/decorate-request-reply.test-d.ts +18 -0
  317. package/test/types/dummy-plugin.ts +9 -0
  318. package/test/types/errors.test-d.ts +90 -0
  319. package/test/types/fastify.test-d.ts +352 -0
  320. package/test/types/hooks.test-d.ts +550 -0
  321. package/test/types/import.ts +2 -0
  322. package/test/types/instance.test-d.ts +588 -0
  323. package/test/types/logger.test-d.ts +277 -0
  324. package/test/types/plugin.test-d.ts +97 -0
  325. package/test/types/register.test-d.ts +237 -0
  326. package/test/types/reply.test-d.ts +254 -0
  327. package/test/types/request.test-d.ts +188 -0
  328. package/test/types/route.test-d.ts +553 -0
  329. package/test/types/schema.test-d.ts +135 -0
  330. package/test/types/serverFactory.test-d.ts +37 -0
  331. package/test/types/type-provider.test-d.ts +1213 -0
  332. package/test/types/using.test-d.ts +17 -0
  333. package/test/upgrade.test.js +52 -0
  334. package/test/url-rewriting.test.js +122 -0
  335. package/test/use-semicolon-delimiter.test.js +168 -0
  336. package/test/validation-error-handling.test.js +900 -0
  337. package/test/versioned-routes.test.js +603 -0
  338. package/test/web-api.test.js +616 -0
  339. package/test/wrap-thenable.test.js +30 -0
  340. package/types/content-type-parser.d.ts +75 -0
  341. package/types/context.d.ts +22 -0
  342. package/types/errors.d.ts +92 -0
  343. package/types/hooks.d.ts +875 -0
  344. package/types/instance.d.ts +609 -0
  345. package/types/logger.d.ts +107 -0
  346. package/types/plugin.d.ts +44 -0
  347. package/types/register.d.ts +42 -0
  348. package/types/reply.d.ts +81 -0
  349. package/types/request.d.ts +95 -0
  350. package/types/route.d.ts +199 -0
  351. package/types/schema.d.ts +61 -0
  352. package/types/server-factory.d.ts +19 -0
  353. package/types/type-provider.d.ts +130 -0
  354. 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