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,506 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+
5
+ const Request = require('../../lib/request')
6
+ const Context = require('../../lib/context')
7
+ const {
8
+ kReply,
9
+ kRequest,
10
+ kOptions
11
+ } = require('../../lib/symbols')
12
+
13
+ process.removeAllListeners('warning')
14
+
15
+ test('Regular request', t => {
16
+ const headers = {
17
+ host: 'hostname'
18
+ }
19
+ const req = {
20
+ method: 'GET',
21
+ url: '/',
22
+ socket: { remoteAddress: 'ip' },
23
+ headers
24
+ }
25
+ const context = new Context({
26
+ schema: {
27
+ body: {
28
+ type: 'object',
29
+ required: ['hello'],
30
+ properties: {
31
+ hello: { type: 'string' }
32
+ }
33
+ }
34
+ },
35
+ config: {
36
+ some: 'config',
37
+ url: req.url,
38
+ method: req.method
39
+ },
40
+ server: {
41
+ [kReply]: {},
42
+ [kRequest]: Request,
43
+ [kOptions]: {
44
+ requestIdLogLabel: 'reqId'
45
+ },
46
+ server: {}
47
+ }
48
+ })
49
+ req.connection = req.socket
50
+ const request = new Request('id', 'params', req, 'query', 'log', context)
51
+ t.assert.ok(request instanceof Request)
52
+ t.assert.ok(request.validateInput instanceof Function)
53
+ t.assert.ok(request.getValidationFunction instanceof Function)
54
+ t.assert.ok(request.compileValidationSchema instanceof Function)
55
+ t.assert.strictEqual(request.id, 'id')
56
+ t.assert.strictEqual(request.params, 'params')
57
+ t.assert.strictEqual(request.raw, req)
58
+ t.assert.strictEqual(request.query, 'query')
59
+ t.assert.strictEqual(request.headers, headers)
60
+ t.assert.strictEqual(request.log, 'log')
61
+ t.assert.strictEqual(request.ip, 'ip')
62
+ t.assert.strictEqual(request.ips, undefined)
63
+ t.assert.strictEqual(request.host, 'hostname')
64
+ t.assert.strictEqual(request.body, undefined)
65
+ t.assert.strictEqual(request.method, 'GET')
66
+ t.assert.strictEqual(request.url, '/')
67
+ t.assert.strictEqual(request.originalUrl, '/')
68
+ t.assert.strictEqual(request.socket, req.socket)
69
+ t.assert.strictEqual(request.protocol, 'http')
70
+ // Aim to not bad property keys (including Symbols)
71
+ t.assert.ok(!('undefined' in request))
72
+ })
73
+
74
+ test('Request with undefined config', t => {
75
+ const headers = {
76
+ host: 'hostname'
77
+ }
78
+ const req = {
79
+ method: 'GET',
80
+ url: '/',
81
+ socket: { remoteAddress: 'ip' },
82
+ headers
83
+ }
84
+ const context = new Context({
85
+ schema: {
86
+ body: {
87
+ type: 'object',
88
+ required: ['hello'],
89
+ properties: {
90
+ hello: { type: 'string' }
91
+ }
92
+ }
93
+ },
94
+ server: {
95
+ [kReply]: {},
96
+ [kRequest]: Request,
97
+ [kOptions]: {
98
+ requestIdLogLabel: 'reqId'
99
+ },
100
+ server: {}
101
+ }
102
+ })
103
+ req.connection = req.socket
104
+ const request = new Request('id', 'params', req, 'query', 'log', context)
105
+ t.assert.ok(request, Request)
106
+ t.assert.ok(request.validateInput, Function)
107
+ t.assert.ok(request.getValidationFunction, Function)
108
+ t.assert.ok(request.compileValidationSchema, Function)
109
+ t.assert.strictEqual(request.id, 'id')
110
+ t.assert.strictEqual(request.params, 'params')
111
+ t.assert.strictEqual(request.raw, req)
112
+ t.assert.strictEqual(request.query, 'query')
113
+ t.assert.strictEqual(request.headers, headers)
114
+ t.assert.strictEqual(request.log, 'log')
115
+ t.assert.strictEqual(request.ip, 'ip')
116
+ t.assert.strictEqual(request.ips, undefined)
117
+ t.assert.strictEqual(request.hostname, 'hostname')
118
+ t.assert.strictEqual(request.body, undefined)
119
+ t.assert.strictEqual(request.method, 'GET')
120
+ t.assert.strictEqual(request.url, '/')
121
+ t.assert.strictEqual(request.originalUrl, '/')
122
+ t.assert.strictEqual(request.socket, req.socket)
123
+ t.assert.strictEqual(request.protocol, 'http')
124
+
125
+ // Aim to not bad property keys (including Symbols)
126
+ t.assert.ok(!('undefined' in request))
127
+ })
128
+
129
+ test('Regular request - hostname from authority', t => {
130
+ t.plan(3)
131
+ const headers = {
132
+ ':authority': 'authority'
133
+ }
134
+ const req = {
135
+ method: 'GET',
136
+ url: '/',
137
+ socket: { remoteAddress: 'ip' },
138
+ headers
139
+ }
140
+ const context = new Context({
141
+ schema: {
142
+ body: {
143
+ type: 'object',
144
+ required: ['hello'],
145
+ properties: {
146
+ hello: { type: 'string' }
147
+ }
148
+ }
149
+ },
150
+ config: {
151
+ some: 'config',
152
+ url: req.url,
153
+ method: req.method
154
+ },
155
+ server: {
156
+ [kReply]: {},
157
+ [kRequest]: Request,
158
+ [kOptions]: {
159
+ requestIdLogLabel: 'reqId'
160
+ },
161
+ server: {}
162
+ }
163
+ })
164
+
165
+ const request = new Request('id', 'params', req, 'query', 'log', context)
166
+ t.assert.ok(request instanceof Request)
167
+ t.assert.strictEqual(request.host, 'authority')
168
+ t.assert.strictEqual(request.port, null)
169
+ })
170
+
171
+ test('Regular request - host header has precedence over authority', t => {
172
+ t.plan(3)
173
+ const headers = {
174
+ host: 'hostname',
175
+ ':authority': 'authority'
176
+ }
177
+ const req = {
178
+ method: 'GET',
179
+ url: '/',
180
+ socket: { remoteAddress: 'ip' },
181
+ headers
182
+ }
183
+ const context = new Context({
184
+ schema: {
185
+ body: {
186
+ type: 'object',
187
+ required: ['hello'],
188
+ properties: {
189
+ hello: { type: 'string' }
190
+ }
191
+ }
192
+ },
193
+ config: {
194
+ some: 'config',
195
+ url: req.url,
196
+ method: req.method
197
+ },
198
+ server: {
199
+ [kReply]: {},
200
+ [kRequest]: Request,
201
+ [kOptions]: {
202
+ requestIdLogLabel: 'reqId'
203
+ },
204
+ server: {}
205
+ }
206
+ })
207
+ const request = new Request('id', 'params', req, 'query', 'log', context)
208
+ t.assert.ok(request instanceof Request)
209
+ t.assert.strictEqual(request.host, 'hostname')
210
+ t.assert.strictEqual(request.port, null)
211
+ })
212
+
213
+ test('Request with trust proxy', t => {
214
+ t.plan(18)
215
+ const headers = {
216
+ 'x-forwarded-for': '2.2.2.2, 1.1.1.1',
217
+ 'x-forwarded-host': 'fastify.test'
218
+ }
219
+ const req = {
220
+ method: 'GET',
221
+ url: '/',
222
+ socket: { remoteAddress: 'ip' },
223
+ headers
224
+ }
225
+ const context = new Context({
226
+ schema: {
227
+ body: {
228
+ type: 'object',
229
+ required: ['hello'],
230
+ properties: {
231
+ hello: { type: 'string' }
232
+ }
233
+ }
234
+ },
235
+ config: {
236
+ some: 'config',
237
+ url: req.url,
238
+ method: req.method
239
+ },
240
+ server: {
241
+ [kReply]: {},
242
+ [kRequest]: Request,
243
+ [kOptions]: {
244
+ requestIdLogLabel: 'reqId'
245
+ }
246
+ }
247
+ })
248
+
249
+ const TpRequest = Request.buildRequest(Request, true)
250
+ const request = new TpRequest('id', 'params', req, 'query', 'log', context)
251
+ t.assert.ok(request instanceof TpRequest)
252
+ t.assert.strictEqual(request.id, 'id')
253
+ t.assert.strictEqual(request.params, 'params')
254
+ t.assert.deepStrictEqual(request.raw, req)
255
+ t.assert.strictEqual(request.query, 'query')
256
+ t.assert.strictEqual(request.headers, headers)
257
+ t.assert.strictEqual(request.log, 'log')
258
+ t.assert.strictEqual(request.ip, '2.2.2.2')
259
+ t.assert.deepStrictEqual(request.ips, ['ip', '1.1.1.1', '2.2.2.2'])
260
+ t.assert.strictEqual(request.host, 'fastify.test')
261
+ t.assert.strictEqual(request.body, undefined)
262
+ t.assert.strictEqual(request.method, 'GET')
263
+ t.assert.strictEqual(request.url, '/')
264
+ t.assert.strictEqual(request.socket, req.socket)
265
+ t.assert.strictEqual(request.protocol, 'http')
266
+ t.assert.ok(request.validateInput instanceof Function)
267
+ t.assert.ok(request.getValidationFunction instanceof Function)
268
+ t.assert.ok(request.compileValidationSchema instanceof Function)
269
+ })
270
+
271
+ test('Request with trust proxy, encrypted', t => {
272
+ t.plan(2)
273
+ const headers = {
274
+ 'x-forwarded-for': '2.2.2.2, 1.1.1.1',
275
+ 'x-forwarded-host': 'fastify.test'
276
+ }
277
+ const req = {
278
+ method: 'GET',
279
+ url: '/',
280
+ socket: { remoteAddress: 'ip', encrypted: true },
281
+ headers
282
+ }
283
+
284
+ const TpRequest = Request.buildRequest(Request, true)
285
+ const request = new TpRequest('id', 'params', req, 'query', 'log')
286
+ t.assert.ok(request instanceof TpRequest)
287
+ t.assert.strictEqual(request.protocol, 'https')
288
+ })
289
+
290
+ test('Request with trust proxy - no x-forwarded-host header', t => {
291
+ t.plan(2)
292
+ const headers = {
293
+ 'x-forwarded-for': '2.2.2.2, 1.1.1.1',
294
+ host: 'hostname'
295
+ }
296
+ const req = {
297
+ method: 'GET',
298
+ url: '/',
299
+ socket: { remoteAddress: 'ip' },
300
+ headers
301
+ }
302
+ const context = new Context({
303
+ schema: {
304
+ body: {
305
+ type: 'object',
306
+ required: ['hello'],
307
+ properties: {
308
+ hello: { type: 'string' }
309
+ }
310
+ }
311
+ },
312
+ config: {
313
+ some: 'config',
314
+ url: req.url,
315
+ method: req.method
316
+ },
317
+ server: {
318
+ [kReply]: {},
319
+ [kRequest]: Request,
320
+ [kOptions]: {
321
+ requestIdLogLabel: 'reqId'
322
+ },
323
+ server: {}
324
+ }
325
+ })
326
+
327
+ const TpRequest = Request.buildRequest(Request, true)
328
+ const request = new TpRequest('id', 'params', req, 'query', 'log', context)
329
+ t.assert.ok(request instanceof TpRequest)
330
+ t.assert.strictEqual(request.host, 'hostname')
331
+ })
332
+
333
+ test('Request with trust proxy - no x-forwarded-host header and fallback to authority', t => {
334
+ t.plan(2)
335
+ const headers = {
336
+ 'x-forwarded-for': '2.2.2.2, 1.1.1.1',
337
+ ':authority': 'authority'
338
+ }
339
+ const req = {
340
+ method: 'GET',
341
+ url: '/',
342
+ socket: { remoteAddress: 'ip' },
343
+ headers
344
+ }
345
+ const context = new Context({
346
+ schema: {
347
+ body: {
348
+ type: 'object',
349
+ required: ['hello'],
350
+ properties: {
351
+ hello: { type: 'string' }
352
+ }
353
+ }
354
+ },
355
+ config: {
356
+ some: 'config',
357
+ url: req.url,
358
+ method: req.method
359
+ },
360
+ server: {
361
+ [kReply]: {},
362
+ [kRequest]: Request,
363
+ [kOptions]: {
364
+ requestIdLogLabel: 'reqId'
365
+ },
366
+ server: {}
367
+ }
368
+ })
369
+
370
+ const TpRequest = Request.buildRequest(Request, true)
371
+ const request = new TpRequest('id', 'params', req, 'query', 'log', context)
372
+ t.assert.ok(request instanceof TpRequest)
373
+ t.assert.strictEqual(request.host, 'authority')
374
+ })
375
+
376
+ test('Request with trust proxy - x-forwarded-host header has precedence over host', t => {
377
+ t.plan(2)
378
+ const headers = {
379
+ 'x-forwarded-for': ' 2.2.2.2, 1.1.1.1',
380
+ 'x-forwarded-host': 'fastify.test',
381
+ host: 'hostname'
382
+ }
383
+ const req = {
384
+ method: 'GET',
385
+ url: '/',
386
+ socket: { remoteAddress: 'ip' },
387
+ headers
388
+ }
389
+
390
+ const TpRequest = Request.buildRequest(Request, true)
391
+ const request = new TpRequest('id', 'params', req, 'query', 'log')
392
+ t.assert.ok(request instanceof TpRequest)
393
+ t.assert.strictEqual(request.host, 'fastify.test')
394
+ })
395
+
396
+ test('Request with trust proxy - handles multiple entries in x-forwarded-host/proto', t => {
397
+ t.plan(3)
398
+ const headers = {
399
+ 'x-forwarded-host': 'example2.com, fastify.test',
400
+ 'x-forwarded-proto': 'http, https'
401
+ }
402
+ const req = {
403
+ method: 'GET',
404
+ url: '/',
405
+ socket: { remoteAddress: 'ip' },
406
+ headers
407
+ }
408
+
409
+ const TpRequest = Request.buildRequest(Request, true)
410
+ const request = new TpRequest('id', 'params', req, 'query', 'log')
411
+ t.assert.ok(request instanceof TpRequest)
412
+ t.assert.strictEqual(request.host, 'fastify.test')
413
+ t.assert.strictEqual(request.protocol, 'https')
414
+ })
415
+
416
+ test('Request with trust proxy - plain', t => {
417
+ t.plan(1)
418
+ const headers = {
419
+ 'x-forwarded-for': '2.2.2.2, 1.1.1.1',
420
+ 'x-forwarded-host': 'fastify.test'
421
+ }
422
+ const req = {
423
+ method: 'GET',
424
+ url: '/',
425
+ socket: { remoteAddress: 'ip' },
426
+ headers
427
+ }
428
+
429
+ const TpRequest = Request.buildRequest(Request, true)
430
+ const request = new TpRequest('id', 'params', req, 'query', 'log')
431
+ t.assert.deepStrictEqual(request.protocol, 'http')
432
+ })
433
+
434
+ test('Request with undefined socket', t => {
435
+ t.plan(18)
436
+ const headers = {
437
+ host: 'hostname'
438
+ }
439
+ const req = {
440
+ method: 'GET',
441
+ url: '/',
442
+ socket: undefined,
443
+ headers
444
+ }
445
+ const context = new Context({
446
+ schema: {
447
+ body: {
448
+ type: 'object',
449
+ required: ['hello'],
450
+ properties: {
451
+ hello: { type: 'string' }
452
+ }
453
+ }
454
+ },
455
+ config: {
456
+ some: 'config',
457
+ url: req.url,
458
+ method: req.method
459
+ },
460
+ server: {
461
+ [kReply]: {},
462
+ [kRequest]: Request,
463
+ [kOptions]: {
464
+ requestIdLogLabel: 'reqId'
465
+ },
466
+ server: {}
467
+ }
468
+ })
469
+ const request = new Request('id', 'params', req, 'query', 'log', context)
470
+ t.assert.ok(request instanceof Request)
471
+ t.assert.strictEqual(request.id, 'id')
472
+ t.assert.strictEqual(request.params, 'params')
473
+ t.assert.deepStrictEqual(request.raw, req)
474
+ t.assert.strictEqual(request.query, 'query')
475
+ t.assert.strictEqual(request.headers, headers)
476
+ t.assert.strictEqual(request.log, 'log')
477
+ t.assert.strictEqual(request.ip, undefined)
478
+ t.assert.strictEqual(request.ips, undefined)
479
+ t.assert.strictEqual(request.host, 'hostname')
480
+ t.assert.deepStrictEqual(request.body, undefined)
481
+ t.assert.strictEqual(request.method, 'GET')
482
+ t.assert.strictEqual(request.url, '/')
483
+ t.assert.strictEqual(request.protocol, undefined)
484
+ t.assert.deepStrictEqual(request.socket, req.socket)
485
+ t.assert.ok(request.validateInput instanceof Function)
486
+ t.assert.ok(request.getValidationFunction instanceof Function)
487
+ t.assert.ok(request.compileValidationSchema instanceof Function)
488
+ })
489
+
490
+ test('Request with trust proxy and undefined socket', t => {
491
+ t.plan(1)
492
+ const headers = {
493
+ 'x-forwarded-for': '2.2.2.2, 1.1.1.1',
494
+ 'x-forwarded-host': 'fastify.test'
495
+ }
496
+ const req = {
497
+ method: 'GET',
498
+ url: '/',
499
+ socket: undefined,
500
+ headers
501
+ }
502
+
503
+ const TpRequest = Request.buildRequest(Request, true)
504
+ const request = new TpRequest('id', 'params', req, 'query', 'log')
505
+ t.assert.deepStrictEqual(request.protocol, undefined)
506
+ })
@@ -0,0 +1,40 @@
1
+ const { sep } = require('node:path')
2
+ const { test } = require('node:test')
3
+ const Fastify = require('../../fastify')
4
+
5
+ test('SchemaController are NOT loaded when the controllers are custom', async t => {
6
+ const app = Fastify({
7
+ schemaController: {
8
+ compilersFactory: {
9
+ buildValidator: () => () => { },
10
+ buildSerializer: () => () => { }
11
+ }
12
+ }
13
+ })
14
+
15
+ await app.ready()
16
+
17
+ const loaded = Object.keys(require.cache)
18
+ const ajvModule = loaded.find((path) => path.includes(`@fastify${sep}ajv-compiler`))
19
+ const stringifyModule = loaded.find((path) => path.includes(`@fastify${sep}fast-json-stringify-compiler`))
20
+
21
+ t.assert.equal(ajvModule, undefined, 'Ajv compiler is loaded')
22
+ t.assert.equal(stringifyModule, undefined, 'Stringify compiler is loaded')
23
+ })
24
+
25
+ test('SchemaController are loaded when the controllers are not custom', async t => {
26
+ const app = Fastify()
27
+ await app.ready()
28
+
29
+ const loaded = Object.keys(require.cache)
30
+ const ajvModule = loaded.find((path) => path.includes(`@fastify${sep}ajv-compiler`))
31
+ const stringifyModule = loaded.find((path) => path.includes(`@fastify${sep}fast-json-stringify-compiler`))
32
+
33
+ t.after(() => {
34
+ delete require.cache[ajvModule]
35
+ delete require.cache[stringifyModule]
36
+ })
37
+
38
+ t.assert.ok(ajvModule, 'Ajv compiler is loaded')
39
+ t.assert.ok(stringifyModule, 'Stringify compiler is loaded')
40
+ })
@@ -0,0 +1,91 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const proxyquire = require('proxyquire')
5
+
6
+ const Fastify = require('../../fastify')
7
+ const { createServer } = require('../../lib/server')
8
+
9
+ const handler = (req, res) => {
10
+ res.writeHead(200, { 'Content-Type': 'application/json' })
11
+ res.end(JSON.stringify({ data: 'Hello World!' }))
12
+ }
13
+
14
+ test('start listening', async t => {
15
+ const { server, listen } = createServer({}, handler)
16
+ await listen.call(Fastify(), { port: 0, host: 'localhost' })
17
+ server.close()
18
+ t.assert.ok(true, 'server started')
19
+ })
20
+
21
+ test('DNS errors does not stop the main server on localhost - promise interface', async t => {
22
+ const { createServer } = proxyquire('../../lib/server', {
23
+ 'node:dns': {
24
+ lookup: (hostname, options, cb) => {
25
+ cb(new Error('DNS error'))
26
+ }
27
+ }
28
+ })
29
+ const { server, listen } = createServer({}, handler)
30
+ await listen.call(Fastify(), { port: 0, host: 'localhost' })
31
+ server.close()
32
+ t.assert.ok(true, 'server started')
33
+ })
34
+
35
+ test('DNS errors does not stop the main server on localhost - callback interface', (t, done) => {
36
+ t.plan(2)
37
+ const { createServer } = proxyquire('../../lib/server', {
38
+ 'node:dns': {
39
+ lookup: (hostname, options, cb) => {
40
+ cb(new Error('DNS error'))
41
+ }
42
+ }
43
+ })
44
+ const { server, listen } = createServer({}, handler)
45
+ listen.call(Fastify(), { port: 0, host: 'localhost' }, (err) => {
46
+ t.assert.ifError(err)
47
+ server.close()
48
+ t.assert.ok(true, 'server started')
49
+ done()
50
+ })
51
+ })
52
+
53
+ test('DNS returns empty binding', (t, done) => {
54
+ t.plan(2)
55
+ const { createServer } = proxyquire('../../lib/server', {
56
+ 'node:dns': {
57
+ lookup: (hostname, options, cb) => {
58
+ cb(null, [])
59
+ }
60
+ }
61
+ })
62
+ const { server, listen } = createServer({}, handler)
63
+ listen.call(Fastify(), { port: 0, host: 'localhost' }, (err) => {
64
+ t.assert.ifError(err)
65
+ server.close()
66
+ t.assert.ok(true, 'server started')
67
+ done()
68
+ })
69
+ })
70
+
71
+ test('DNS returns more than two binding', (t, done) => {
72
+ t.plan(2)
73
+ const { createServer } = proxyquire('../../lib/server', {
74
+ 'node:dns': {
75
+ lookup: (hostname, options, cb) => {
76
+ cb(null, [
77
+ { address: '::1', family: 6 },
78
+ { address: '127.0.0.1', family: 4 },
79
+ { address: '0.0.0.0', family: 4 }
80
+ ])
81
+ }
82
+ }
83
+ })
84
+ const { server, listen } = createServer({}, handler)
85
+ listen.call(Fastify(), { port: 0, host: 'localhost' }, (err) => {
86
+ t.assert.ifError(err)
87
+ server.close()
88
+ t.assert.ok(true, 'server started')
89
+ done()
90
+ })
91
+ })