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,113 @@
1
+ 'use strict'
2
+
3
+ const { test, before } = require('node:test')
4
+ const Fastify = require('..')
5
+ const helper = require('./helper')
6
+ const { networkInterfaces } = require('node:os')
7
+
8
+ const isIPv6Missing = !Object.values(networkInterfaces()).flat().some(({ family }) => family === 'IPv6')
9
+
10
+ let localhostForURL
11
+
12
+ before(async function () {
13
+ [, localhostForURL] = await helper.getLoopbackHost()
14
+ })
15
+
16
+ test('register after listen using Promise.resolve()', async t => {
17
+ t.plan(1)
18
+ const fastify = Fastify()
19
+
20
+ const handler = (req, res) => res.send({})
21
+ await Promise.resolve()
22
+ .then(() => {
23
+ fastify.get('/', handler)
24
+ fastify.register((f2, options, done) => {
25
+ f2.get('/plugin', handler)
26
+ done()
27
+ })
28
+ return fastify.ready()
29
+ })
30
+ .catch((err) => {
31
+ t.assert.fail(err.message)
32
+ })
33
+ .then(() => t.assert.ok('resolved'))
34
+ })
35
+
36
+ test('double listen errors', (t, done) => {
37
+ t.plan(3)
38
+ const fastify = Fastify()
39
+ t.after(() => fastify.close())
40
+ fastify.listen({ port: 0 }, (err) => {
41
+ t.assert.ifError(err)
42
+ fastify.listen({ port: fastify.server.address().port }, (err, address) => {
43
+ t.assert.strictEqual(address, null)
44
+ t.assert.ok(err)
45
+ done()
46
+ })
47
+ })
48
+ })
49
+
50
+ test('double listen errors callback with (err, address)', (t, done) => {
51
+ t.plan(4)
52
+ const fastify = Fastify()
53
+ t.after(() => fastify.close())
54
+ fastify.listen({ port: 0 }, (err1, address1) => {
55
+ t.assert.strictEqual(address1, `http://${localhostForURL}:${fastify.server.address().port}`)
56
+ t.assert.ifError(err1)
57
+ fastify.listen({ port: fastify.server.address().port }, (err2, address2) => {
58
+ t.assert.strictEqual(address2, null)
59
+ t.assert.ok(err2)
60
+ done()
61
+ })
62
+ })
63
+ })
64
+
65
+ test('nonlocalhost double listen errors callback with (err, address)', { skip: isIPv6Missing }, (t, done) => {
66
+ t.plan(4)
67
+ const fastify = Fastify()
68
+ t.after(() => fastify.close())
69
+ fastify.listen({ host: '::1', port: 0 }, (err, address) => {
70
+ t.assert.strictEqual(address, `http://${'[::1]'}:${fastify.server.address().port}`)
71
+ t.assert.ifError(err)
72
+ fastify.listen({ host: '::1', port: fastify.server.address().port }, (err2, address2) => {
73
+ t.assert.strictEqual(address2, null)
74
+ t.assert.ok(err2)
75
+ done()
76
+ })
77
+ })
78
+ })
79
+
80
+ test('listen twice on the same port', (t, done) => {
81
+ t.plan(4)
82
+ const fastify = Fastify()
83
+ t.after(() => fastify.close())
84
+ fastify.listen({ port: 0 }, (err1, address1) => {
85
+ t.assert.strictEqual(address1, `http://${localhostForURL}:${fastify.server.address().port}`)
86
+ t.assert.ifError(err1)
87
+ const s2 = Fastify()
88
+ t.after(() => fastify.close())
89
+ s2.listen({ port: fastify.server.address().port }, (err2, address2) => {
90
+ t.assert.strictEqual(address2, null)
91
+ t.assert.ok(err2)
92
+ done()
93
+ })
94
+ })
95
+ })
96
+
97
+ test('listen twice on the same port callback with (err, address)', (t, done) => {
98
+ t.plan(4)
99
+ const fastify = Fastify()
100
+ t.after(() => fastify.close())
101
+ fastify.listen({ port: 0 }, (err1, address1) => {
102
+ const _port = fastify.server.address().port
103
+ t.assert.strictEqual(address1, `http://${localhostForURL}:${_port}`)
104
+ t.assert.ifError(err1)
105
+ const s2 = Fastify()
106
+ t.after(() => fastify.close())
107
+ s2.listen({ port: _port }, (err2, address2) => {
108
+ t.assert.strictEqual(address2, null)
109
+ t.assert.ok(err2)
110
+ done()
111
+ })
112
+ })
113
+ })
@@ -0,0 +1,83 @@
1
+ 'use strict'
2
+
3
+ const os = require('node:os')
4
+ const path = require('node:path')
5
+ const fs = require('node:fs')
6
+ const { test, before } = require('node:test')
7
+ const Fastify = require('..')
8
+ const helper = require('./helper')
9
+
10
+ let localhostForURL
11
+
12
+ before(async function () {
13
+ [, localhostForURL] = await helper.getLoopbackHost()
14
+ })
15
+
16
+ // https://nodejs.org/api/net.html#net_ipc_support
17
+ if (os.platform() !== 'win32') {
18
+ test('listen on socket', async t => {
19
+ t.plan(2)
20
+ const fastify = Fastify()
21
+ t.after(() => fastify.close())
22
+
23
+ const sockFile = path.join(os.tmpdir(), `${(Math.random().toString(16) + '0000000').slice(2, 10)}-server.sock`)
24
+ try {
25
+ fs.unlinkSync(sockFile)
26
+ } catch (e) { }
27
+
28
+ await fastify.listen({ path: sockFile })
29
+ t.assert.deepStrictEqual(fastify.addresses(), [sockFile])
30
+ t.assert.strictEqual(fastify.server.address(), sockFile)
31
+ })
32
+ } else {
33
+ test('listen on socket', async t => {
34
+ t.plan(2)
35
+ const fastify = Fastify()
36
+ t.after(() => fastify.close())
37
+
38
+ const sockFile = `\\\\.\\pipe\\${(Math.random().toString(16) + '0000000').slice(2, 10)}-server-sock`
39
+
40
+ await fastify.listen({ path: sockFile })
41
+ t.assert.deepStrictEqual(fastify.addresses(), [sockFile])
42
+ t.assert.strictEqual(fastify.server.address(), sockFile)
43
+ })
44
+ }
45
+
46
+ test('listen without callback with (address)', async t => {
47
+ t.plan(1)
48
+ const fastify = Fastify()
49
+ t.after(() => fastify.close())
50
+ const address = await fastify.listen({ port: 0 })
51
+ t.assert.strictEqual(address, `http://${localhostForURL}:${fastify.server.address().port}`)
52
+ })
53
+
54
+ test('double listen without callback rejects', (t, done) => {
55
+ t.plan(1)
56
+ const fastify = Fastify()
57
+ t.after(() => fastify.close())
58
+ fastify.listen({ port: 0 })
59
+ .then(() => {
60
+ fastify.listen({ port: 0 })
61
+ .catch(err => {
62
+ t.assert.ok(err)
63
+ done()
64
+ })
65
+ })
66
+ .catch(err => t.assert.ifError(err))
67
+ })
68
+
69
+ test('double listen without callback with (address)', (t, done) => {
70
+ t.plan(2)
71
+ const fastify = Fastify()
72
+ t.after(() => fastify.close())
73
+ fastify.listen({ port: 0 })
74
+ .then(address => {
75
+ t.assert.strictEqual(address, `http://${localhostForURL}:${fastify.server.address().port}`)
76
+ fastify.listen({ port: 0 })
77
+ .catch(err => {
78
+ t.assert.ok(err)
79
+ done()
80
+ })
81
+ })
82
+ .catch(err => t.assert.ifError(err))
83
+ })
@@ -0,0 +1,168 @@
1
+ 'use strict'
2
+
3
+ const { test, before } = require('node:test')
4
+ const dns = require('node:dns').promises
5
+ const dnsCb = require('node:dns')
6
+ const Fastify = require('../fastify')
7
+ const helper = require('./helper')
8
+
9
+ let localhostForURL
10
+
11
+ function getUrl (fastify, lookup) {
12
+ const { port } = fastify.server.address()
13
+ if (lookup.family === 6) {
14
+ return `http://[${lookup.address}]:${port}/`
15
+ } else {
16
+ return `http://${lookup.address}:${port}/`
17
+ }
18
+ }
19
+
20
+ before(async function () {
21
+ [, localhostForURL] = await helper.getLoopbackHost()
22
+ })
23
+
24
+ test('listen twice on the same port without callback rejects', (t, done) => {
25
+ t.plan(1)
26
+ const fastify = Fastify()
27
+ t.after(() => fastify.close())
28
+
29
+ fastify.listen({ port: 0 })
30
+ .then(() => {
31
+ const server2 = Fastify()
32
+ t.after(() => server2.close())
33
+ server2.listen({ port: fastify.server.address().port })
34
+ .catch(err => {
35
+ t.assert.ok(err)
36
+ done()
37
+ })
38
+ })
39
+ .catch(err => {
40
+ t.assert.ifError(err)
41
+ })
42
+ })
43
+
44
+ test('listen twice on the same port without callback rejects with (address)', (t, done) => {
45
+ t.plan(2)
46
+ const fastify = Fastify()
47
+ t.after(() => fastify.close())
48
+ fastify.listen({ port: 0 })
49
+ .then(address => {
50
+ const server2 = Fastify()
51
+ t.after(() => server2.close())
52
+ t.assert.strictEqual(address, `http://${localhostForURL}:${fastify.server.address().port}`)
53
+
54
+ server2.listen({ port: fastify.server.address().port })
55
+ .catch(err => {
56
+ t.assert.ok(err)
57
+ done()
58
+ })
59
+ })
60
+ .catch(err => {
61
+ t.assert.ifError(err)
62
+ })
63
+ })
64
+
65
+ test('listen on invalid port without callback rejects', t => {
66
+ const fastify = Fastify()
67
+ t.after(() => fastify.close())
68
+ return fastify.listen({ port: -1 })
69
+ .catch(err => {
70
+ t.assert.ok(err)
71
+ return true
72
+ })
73
+ })
74
+
75
+ test('listen logs the port as info', async t => {
76
+ t.plan(1)
77
+ const fastify = Fastify()
78
+ t.after(() => fastify.close())
79
+
80
+ const msgs = []
81
+ fastify.log.info = function (msg) {
82
+ msgs.push(msg)
83
+ }
84
+
85
+ await fastify.listen({ port: 0 })
86
+ t.assert.ok(/http:\/\//.test(msgs[0]))
87
+ })
88
+
89
+ test('listen on localhost binds IPv4 and IPv6 - promise interface', async t => {
90
+ const localAddresses = await dns.lookup('localhost', { all: true })
91
+ t.plan(3 * localAddresses.length)
92
+
93
+ const app = Fastify()
94
+ app.get('/', async () => 'hello localhost')
95
+ t.after(() => app.close())
96
+ await app.listen({ port: 0, host: 'localhost' })
97
+
98
+ for (const lookup of localAddresses) {
99
+ const result = await fetch(getUrl(app, lookup), {
100
+ method: 'GET'
101
+ })
102
+
103
+ t.assert.ok(result.ok)
104
+ t.assert.deepEqual(result.status, 200)
105
+ t.assert.deepStrictEqual(await result.text(), 'hello localhost')
106
+ }
107
+ })
108
+
109
+ test('listen on localhost binds to all interfaces (both IPv4 and IPv6 if present) - callback interface', async (t) => {
110
+ const lookups = await new Promise((resolve, reject) => {
111
+ dnsCb.lookup('localhost', { all: true }, (err, lookups) => {
112
+ if (err) return reject(err)
113
+ resolve(lookups)
114
+ })
115
+ })
116
+
117
+ t.plan(3 * lookups.length)
118
+
119
+ const app = Fastify()
120
+ app.get('/', async () => 'hello localhost')
121
+ t.after(() => app.close())
122
+
123
+ await app.listen({ port: 0, host: 'localhost' })
124
+
125
+ // Loop over each lookup and perform the assertions
126
+ for (const lookup of lookups) {
127
+ const result = await fetch(getUrl(app, lookup), {
128
+ method: 'GET'
129
+ })
130
+
131
+ t.assert.ok(result.ok)
132
+ t.assert.deepEqual(result.status, 200)
133
+ t.assert.deepStrictEqual(await result.text(), 'hello localhost')
134
+ }
135
+ })
136
+
137
+ test('addresses getter', async t => {
138
+ let localAddresses = await dns.lookup('localhost', { all: true })
139
+
140
+ t.plan(4)
141
+ const app = Fastify()
142
+ app.get('/', async () => 'hello localhost')
143
+ t.after(() => app.close())
144
+
145
+ t.assert.deepStrictEqual(app.addresses(), [], 'before ready')
146
+ await app.ready()
147
+
148
+ t.assert.deepStrictEqual(app.addresses(), [], 'after ready')
149
+ await app.listen({ port: 0, host: 'localhost' })
150
+
151
+ // fix citgm
152
+ // dns lookup may have duplicated addresses (rhel8-s390x rhel8-ppc64le debian10-x64)
153
+
154
+ localAddresses = [...new Set([...localAddresses.map(a => JSON.stringify({
155
+ address: a.address,
156
+ family: typeof a.family === 'number' ? 'IPv' + a.family : a.family
157
+ }))])].sort()
158
+
159
+ const appAddresses = app.addresses().map(a => JSON.stringify({
160
+ address: a.address,
161
+ family: typeof a.family === 'number' ? 'IPv' + a.family : a.family
162
+ })).sort()
163
+
164
+ t.assert.deepStrictEqual(appAddresses, localAddresses, 'after listen')
165
+
166
+ await app.close()
167
+ t.assert.deepStrictEqual(app.addresses(), [], 'after close')
168
+ })
@@ -0,0 +1,122 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const net = require('node:net')
5
+ const Fastify = require('../fastify')
6
+ const { once } = require('node:events')
7
+ const { FSTWRN003 } = require('../lib/warnings.js')
8
+
9
+ function createDeferredPromise () {
10
+ const promise = {}
11
+ promise.promise = new Promise((resolve) => {
12
+ promise.resolve = resolve
13
+ })
14
+ return promise
15
+ }
16
+
17
+ test('same port conflict and success should not fire callback multiple times - callback', async (t) => {
18
+ t.plan(7)
19
+ const server = net.createServer()
20
+ server.listen({ port: 0, host: '127.0.0.1' })
21
+ await once(server, 'listening')
22
+ const option = { port: server.address().port, host: server.address().address }
23
+ let count = 0
24
+ const fastify = Fastify()
25
+ const promise = createDeferredPromise()
26
+ function callback (err) {
27
+ switch (count) {
28
+ case 6: {
29
+ // success in here
30
+ t.assert.ifError(err)
31
+ fastify.close((err) => {
32
+ t.assert.ifError(err)
33
+ promise.resolve()
34
+ })
35
+ break
36
+ }
37
+ case 5: {
38
+ server.close()
39
+ setTimeout(() => {
40
+ fastify.listen(option, callback)
41
+ }, 100)
42
+ break
43
+ }
44
+ default: {
45
+ // expect error
46
+ t.assert.strictEqual(err.code, 'EADDRINUSE')
47
+ setTimeout(() => {
48
+ fastify.listen(option, callback)
49
+ }, 100)
50
+ }
51
+ }
52
+ count++
53
+ }
54
+ fastify.listen(option, callback)
55
+ await promise.promise
56
+ })
57
+
58
+ test('same port conflict and success should not fire callback multiple times - promise', async (t) => {
59
+ t.plan(5)
60
+ const server = net.createServer()
61
+ server.listen({ port: 0, host: '127.0.0.1' })
62
+ await once(server, 'listening')
63
+ const option = { port: server.address().port, host: server.address().address }
64
+ const fastify = Fastify()
65
+
66
+ try {
67
+ await fastify.listen(option)
68
+ } catch (err) {
69
+ t.assert.strictEqual(err.code, 'EADDRINUSE')
70
+ }
71
+ try {
72
+ await fastify.listen(option)
73
+ } catch (err) {
74
+ t.assert.strictEqual(err.code, 'EADDRINUSE')
75
+ }
76
+ try {
77
+ await fastify.listen(option)
78
+ } catch (err) {
79
+ t.assert.strictEqual(err.code, 'EADDRINUSE')
80
+ }
81
+ try {
82
+ await fastify.listen(option)
83
+ } catch (err) {
84
+ t.assert.strictEqual(err.code, 'EADDRINUSE')
85
+ }
86
+ try {
87
+ await fastify.listen(option)
88
+ } catch (err) {
89
+ t.assert.strictEqual(err.code, 'EADDRINUSE')
90
+ }
91
+
92
+ server.close()
93
+
94
+ await once(server, 'close')
95
+
96
+ // when ever we can listen, and close properly
97
+ // which means there is no problem on the callback
98
+ await fastify.listen()
99
+ await fastify.close()
100
+ })
101
+
102
+ test('should emit a warning when using async callback', (t, done) => {
103
+ t.plan(2)
104
+
105
+ process.on('warning', onWarning)
106
+ function onWarning (warning) {
107
+ t.assert.strictEqual(warning.name, 'FastifyWarning')
108
+ t.assert.strictEqual(warning.code, FSTWRN003.code)
109
+ }
110
+
111
+ const fastify = Fastify()
112
+
113
+ t.after(async () => {
114
+ await fastify.close()
115
+ process.removeListener('warning', onWarning)
116
+ FSTWRN003.emitted = false
117
+ })
118
+
119
+ fastify.listen({ port: 0 }, async function doNotUseAsyncCallback () {
120
+ done()
121
+ })
122
+ })