node-fastify 5.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.borp.yaml +3 -0
- package/.markdownlint-cli2.yaml +22 -0
- package/.prettierignore +1 -0
- package/GOVERNANCE.md +4 -0
- package/LICENSE +21 -0
- package/PROJECT_CHARTER.md +126 -0
- package/README.md +423 -0
- package/SECURITY.md +220 -0
- package/SPONSORS.md +24 -0
- package/build/build-error-serializer.js +35 -0
- package/build/build-validation.js +169 -0
- package/build/sync-version.js +11 -0
- package/docs/Guides/Benchmarking.md +60 -0
- package/docs/Guides/Database.md +321 -0
- package/docs/Guides/Delay-Accepting-Requests.md +608 -0
- package/docs/Guides/Detecting-When-Clients-Abort.md +172 -0
- package/docs/Guides/Ecosystem.md +726 -0
- package/docs/Guides/Fluent-Schema.md +127 -0
- package/docs/Guides/Getting-Started.md +620 -0
- package/docs/Guides/Index.md +43 -0
- package/docs/Guides/Migration-Guide-V3.md +287 -0
- package/docs/Guides/Migration-Guide-V4.md +267 -0
- package/docs/Guides/Migration-Guide-V5.md +727 -0
- package/docs/Guides/Plugins-Guide.md +520 -0
- package/docs/Guides/Prototype-Poisoning.md +383 -0
- package/docs/Guides/Recommendations.md +378 -0
- package/docs/Guides/Serverless.md +604 -0
- package/docs/Guides/Style-Guide.md +246 -0
- package/docs/Guides/Testing.md +481 -0
- package/docs/Guides/Write-Plugin.md +103 -0
- package/docs/Guides/Write-Type-Provider.md +34 -0
- package/docs/Reference/ContentTypeParser.md +271 -0
- package/docs/Reference/Decorators.md +436 -0
- package/docs/Reference/Encapsulation.md +194 -0
- package/docs/Reference/Errors.md +377 -0
- package/docs/Reference/HTTP2.md +94 -0
- package/docs/Reference/Hooks.md +958 -0
- package/docs/Reference/Index.md +73 -0
- package/docs/Reference/LTS.md +86 -0
- package/docs/Reference/Lifecycle.md +99 -0
- package/docs/Reference/Logging.md +268 -0
- package/docs/Reference/Middleware.md +79 -0
- package/docs/Reference/Plugins.md +245 -0
- package/docs/Reference/Principles.md +73 -0
- package/docs/Reference/Reply.md +1001 -0
- package/docs/Reference/Request.md +295 -0
- package/docs/Reference/Routes.md +802 -0
- package/docs/Reference/Server.md +2389 -0
- package/docs/Reference/Type-Providers.md +256 -0
- package/docs/Reference/TypeScript.md +1729 -0
- package/docs/Reference/Validation-and-Serialization.md +1130 -0
- package/docs/Reference/Warnings.md +58 -0
- package/docs/index.md +24 -0
- package/docs/resources/encapsulation_context.drawio +1 -0
- package/docs/resources/encapsulation_context.svg +3 -0
- package/eslint.config.js +35 -0
- package/examples/asyncawait.js +38 -0
- package/examples/benchmark/body.json +3 -0
- package/examples/benchmark/hooks-benchmark-async-await.js +44 -0
- package/examples/benchmark/hooks-benchmark.js +52 -0
- package/examples/benchmark/parser.js +47 -0
- package/examples/benchmark/simple.js +30 -0
- package/examples/benchmark/webstream.js +27 -0
- package/examples/hooks.js +91 -0
- package/examples/http2.js +39 -0
- package/examples/https.js +38 -0
- package/examples/parser.js +53 -0
- package/examples/plugin.js +12 -0
- package/examples/route-prefix.js +38 -0
- package/examples/shared-schema.js +38 -0
- package/examples/simple-stream.js +20 -0
- package/examples/simple.js +32 -0
- package/examples/simple.mjs +27 -0
- package/examples/typescript-server.ts +79 -0
- package/examples/use-plugin.js +29 -0
- package/fastify.d.ts +253 -0
- package/fastify.js +985 -0
- package/integration/server.js +29 -0
- package/integration/test.sh +23 -0
- package/lib/config-validator.js +1266 -0
- package/lib/content-type-parser.js +413 -0
- package/lib/content-type.js +160 -0
- package/lib/context.js +98 -0
- package/lib/decorate.js +152 -0
- package/lib/error-handler.js +173 -0
- package/lib/error-serializer.js +134 -0
- package/lib/error-status.js +14 -0
- package/lib/errors.js +516 -0
- package/lib/four-oh-four.js +190 -0
- package/lib/handle-request.js +195 -0
- package/lib/head-route.js +45 -0
- package/lib/hooks.js +429 -0
- package/lib/initial-config-validation.js +37 -0
- package/lib/logger-factory.js +136 -0
- package/lib/logger-pino.js +68 -0
- package/lib/noop-set.js +10 -0
- package/lib/plugin-override.js +90 -0
- package/lib/plugin-utils.js +169 -0
- package/lib/promise.js +23 -0
- package/lib/reply.js +1030 -0
- package/lib/req-id-gen-factory.js +52 -0
- package/lib/request.js +391 -0
- package/lib/route.js +686 -0
- package/lib/schema-controller.js +164 -0
- package/lib/schemas.js +207 -0
- package/lib/server.js +441 -0
- package/lib/symbols.js +71 -0
- package/lib/validation.js +280 -0
- package/lib/warnings.js +57 -0
- package/lib/wrap-thenable.js +84 -0
- package/package.json +225 -0
- package/scripts/validate-ecosystem-links.js +179 -0
- package/test/404s.test.js +2035 -0
- package/test/500s.test.js +422 -0
- package/test/allow-unsafe-regex.test.js +92 -0
- package/test/als.test.js +65 -0
- package/test/async-await.test.js +705 -0
- package/test/async-dispose.test.js +20 -0
- package/test/async_hooks.test.js +52 -0
- package/test/body-limit.test.js +224 -0
- package/test/buffer.test.js +74 -0
- package/test/build/error-serializer.test.js +36 -0
- package/test/build/version.test.js +14 -0
- package/test/build-certificate.js +109 -0
- package/test/bundler/README.md +29 -0
- package/test/bundler/esbuild/bundler-test.js +32 -0
- package/test/bundler/esbuild/package.json +10 -0
- package/test/bundler/esbuild/src/fail-plugin-version.js +14 -0
- package/test/bundler/esbuild/src/index.js +9 -0
- package/test/bundler/webpack/bundler-test.js +32 -0
- package/test/bundler/webpack/package.json +11 -0
- package/test/bundler/webpack/src/fail-plugin-version.js +14 -0
- package/test/bundler/webpack/src/index.js +9 -0
- package/test/bundler/webpack/webpack.config.js +15 -0
- package/test/case-insensitive.test.js +102 -0
- package/test/chainable.test.js +40 -0
- package/test/child-logger-factory.test.js +128 -0
- package/test/client-timeout.test.js +38 -0
- package/test/close-pipelining.test.js +78 -0
- package/test/close.test.js +706 -0
- package/test/conditional-pino.test.js +47 -0
- package/test/connection-timeout.test.js +42 -0
- package/test/constrained-routes.test.js +1138 -0
- package/test/content-length.test.js +174 -0
- package/test/content-parser.test.js +739 -0
- package/test/content-type.test.js +181 -0
- package/test/context-config.test.js +164 -0
- package/test/custom-http-server.test.js +118 -0
- package/test/custom-parser-async.test.js +59 -0
- package/test/custom-parser.0.test.js +701 -0
- package/test/custom-parser.1.test.js +266 -0
- package/test/custom-parser.2.test.js +91 -0
- package/test/custom-parser.3.test.js +208 -0
- package/test/custom-parser.4.test.js +218 -0
- package/test/custom-parser.5.test.js +130 -0
- package/test/custom-querystring-parser.test.js +129 -0
- package/test/decorator.test.js +1330 -0
- package/test/delete.test.js +344 -0
- package/test/diagnostics-channel/404.test.js +49 -0
- package/test/diagnostics-channel/async-delay-request.test.js +65 -0
- package/test/diagnostics-channel/async-request.test.js +64 -0
- package/test/diagnostics-channel/error-before-handler.test.js +35 -0
- package/test/diagnostics-channel/error-request.test.js +53 -0
- package/test/diagnostics-channel/error-status.test.js +123 -0
- package/test/diagnostics-channel/init.test.js +50 -0
- package/test/diagnostics-channel/sync-delay-request.test.js +49 -0
- package/test/diagnostics-channel/sync-request-reply.test.js +51 -0
- package/test/diagnostics-channel/sync-request.test.js +54 -0
- package/test/encapsulated-child-logger-factory.test.js +69 -0
- package/test/encapsulated-error-handler.test.js +237 -0
- package/test/esm/errorCodes.test.mjs +10 -0
- package/test/esm/esm.test.mjs +13 -0
- package/test/esm/index.test.js +8 -0
- package/test/esm/named-exports.mjs +14 -0
- package/test/esm/other.mjs +8 -0
- package/test/esm/plugin.mjs +8 -0
- package/test/fastify-instance.test.js +300 -0
- package/test/find-route.test.js +152 -0
- package/test/fluent-schema.test.js +209 -0
- package/test/genReqId.test.js +426 -0
- package/test/handler-context.test.js +45 -0
- package/test/handler-timeout.test.js +367 -0
- package/test/has-route.test.js +88 -0
- package/test/header-overflow.test.js +55 -0
- package/test/helper.js +496 -0
- package/test/hooks-async.test.js +1099 -0
- package/test/hooks.on-listen.test.js +1162 -0
- package/test/hooks.on-ready.test.js +421 -0
- package/test/hooks.test.js +3578 -0
- package/test/http-methods/copy.test.js +35 -0
- package/test/http-methods/custom-http-methods.test.js +114 -0
- package/test/http-methods/get.test.js +412 -0
- package/test/http-methods/head.test.js +263 -0
- package/test/http-methods/lock.test.js +108 -0
- package/test/http-methods/mkcalendar.test.js +143 -0
- package/test/http-methods/mkcol.test.js +35 -0
- package/test/http-methods/move.test.js +42 -0
- package/test/http-methods/propfind.test.js +136 -0
- package/test/http-methods/proppatch.test.js +105 -0
- package/test/http-methods/report.test.js +142 -0
- package/test/http-methods/search.test.js +233 -0
- package/test/http-methods/trace.test.js +21 -0
- package/test/http-methods/unlock.test.js +38 -0
- package/test/http2/closing.test.js +270 -0
- package/test/http2/constraint.test.js +109 -0
- package/test/http2/head.test.js +34 -0
- package/test/http2/plain.test.js +68 -0
- package/test/http2/secure-with-fallback.test.js +113 -0
- package/test/http2/secure.test.js +67 -0
- package/test/http2/unknown-http-method.test.js +34 -0
- package/test/https/custom-https-server.test.js +58 -0
- package/test/https/https.test.js +136 -0
- package/test/imports.test.js +17 -0
- package/test/inject.test.js +502 -0
- package/test/input-validation.js +335 -0
- package/test/internals/all.test.js +38 -0
- package/test/internals/content-type-parser.test.js +111 -0
- package/test/internals/context.test.js +31 -0
- package/test/internals/decorator.test.js +156 -0
- package/test/internals/errors.test.js +982 -0
- package/test/internals/handle-request.test.js +270 -0
- package/test/internals/hook-runner.test.js +449 -0
- package/test/internals/hooks.test.js +96 -0
- package/test/internals/initial-config.test.js +383 -0
- package/test/internals/logger.test.js +163 -0
- package/test/internals/plugin.test.js +170 -0
- package/test/internals/promise.test.js +63 -0
- package/test/internals/reply-serialize.test.js +714 -0
- package/test/internals/reply.test.js +1920 -0
- package/test/internals/req-id-gen-factory.test.js +133 -0
- package/test/internals/request-validate.test.js +1402 -0
- package/test/internals/request.test.js +506 -0
- package/test/internals/schema-controller-perf.test.js +40 -0
- package/test/internals/server.test.js +91 -0
- package/test/internals/validation.test.js +352 -0
- package/test/issue-4959.test.js +118 -0
- package/test/keep-alive-timeout.test.js +42 -0
- package/test/listen.1.test.js +154 -0
- package/test/listen.2.test.js +113 -0
- package/test/listen.3.test.js +83 -0
- package/test/listen.4.test.js +168 -0
- package/test/listen.5.test.js +122 -0
- package/test/logger/instantiation.test.js +341 -0
- package/test/logger/logger-test-utils.js +47 -0
- package/test/logger/logging.test.js +460 -0
- package/test/logger/options.test.js +579 -0
- package/test/logger/request.test.js +292 -0
- package/test/logger/response.test.js +183 -0
- package/test/logger/tap-parallel-not-ok +0 -0
- package/test/max-requests-per-socket.test.js +113 -0
- package/test/middleware.test.js +37 -0
- package/test/noop-set.test.js +19 -0
- package/test/nullable-validation.test.js +187 -0
- package/test/options.error-handler.test.js +5 -0
- package/test/options.test.js +5 -0
- package/test/output-validation.test.js +140 -0
- package/test/patch.error-handler.test.js +5 -0
- package/test/patch.test.js +5 -0
- package/test/plugin.1.test.js +230 -0
- package/test/plugin.2.test.js +314 -0
- package/test/plugin.3.test.js +287 -0
- package/test/plugin.4.test.js +504 -0
- package/test/plugin.helper.js +8 -0
- package/test/plugin.name.display.js +10 -0
- package/test/post-empty-body.test.js +38 -0
- package/test/pretty-print.test.js +366 -0
- package/test/promises.test.js +125 -0
- package/test/proto-poisoning.test.js +145 -0
- package/test/put.error-handler.test.js +5 -0
- package/test/put.test.js +5 -0
- package/test/register.test.js +184 -0
- package/test/reply-code.test.js +148 -0
- package/test/reply-early-hints.test.js +100 -0
- package/test/reply-error.test.js +815 -0
- package/test/reply-trailers.test.js +445 -0
- package/test/reply-web-stream-locked.test.js +37 -0
- package/test/request-error.test.js +624 -0
- package/test/request-header-host.test.js +339 -0
- package/test/request-id.test.js +118 -0
- package/test/request-timeout.test.js +53 -0
- package/test/route-hooks.test.js +635 -0
- package/test/route-prefix.test.js +904 -0
- package/test/route-shorthand.test.js +48 -0
- package/test/route.1.test.js +259 -0
- package/test/route.2.test.js +100 -0
- package/test/route.3.test.js +213 -0
- package/test/route.4.test.js +127 -0
- package/test/route.5.test.js +211 -0
- package/test/route.6.test.js +306 -0
- package/test/route.7.test.js +406 -0
- package/test/route.8.test.js +225 -0
- package/test/router-options.test.js +1108 -0
- package/test/same-shape.test.js +124 -0
- package/test/schema-examples.test.js +661 -0
- package/test/schema-feature.test.js +2198 -0
- package/test/schema-serialization.test.js +1171 -0
- package/test/schema-special-usage.test.js +1348 -0
- package/test/schema-validation.test.js +1572 -0
- package/test/scripts/validate-ecosystem-links.test.js +339 -0
- package/test/serialize-response.test.js +186 -0
- package/test/server.test.js +347 -0
- package/test/set-error-handler.test.js +69 -0
- package/test/skip-reply-send.test.js +317 -0
- package/test/stream-serializers.test.js +40 -0
- package/test/stream.1.test.js +94 -0
- package/test/stream.2.test.js +129 -0
- package/test/stream.3.test.js +198 -0
- package/test/stream.4.test.js +176 -0
- package/test/stream.5.test.js +188 -0
- package/test/sync-routes.test.js +32 -0
- package/test/throw.test.js +359 -0
- package/test/toolkit.js +63 -0
- package/test/trust-proxy.test.js +162 -0
- package/test/type-provider.test.js +22 -0
- package/test/types/content-type-parser.test-d.ts +72 -0
- package/test/types/decorate-request-reply.test-d.ts +18 -0
- package/test/types/dummy-plugin.ts +9 -0
- package/test/types/errors.test-d.ts +90 -0
- package/test/types/fastify.test-d.ts +352 -0
- package/test/types/hooks.test-d.ts +550 -0
- package/test/types/import.ts +2 -0
- package/test/types/instance.test-d.ts +588 -0
- package/test/types/logger.test-d.ts +277 -0
- package/test/types/plugin.test-d.ts +97 -0
- package/test/types/register.test-d.ts +237 -0
- package/test/types/reply.test-d.ts +254 -0
- package/test/types/request.test-d.ts +188 -0
- package/test/types/route.test-d.ts +553 -0
- package/test/types/schema.test-d.ts +135 -0
- package/test/types/serverFactory.test-d.ts +37 -0
- package/test/types/type-provider.test-d.ts +1213 -0
- package/test/types/using.test-d.ts +17 -0
- package/test/upgrade.test.js +52 -0
- package/test/url-rewriting.test.js +122 -0
- package/test/use-semicolon-delimiter.test.js +168 -0
- package/test/validation-error-handling.test.js +900 -0
- package/test/versioned-routes.test.js +603 -0
- package/test/web-api.test.js +616 -0
- package/test/wrap-thenable.test.js +30 -0
- package/types/content-type-parser.d.ts +75 -0
- package/types/context.d.ts +22 -0
- package/types/errors.d.ts +92 -0
- package/types/hooks.d.ts +875 -0
- package/types/instance.d.ts +609 -0
- package/types/logger.d.ts +107 -0
- package/types/plugin.d.ts +44 -0
- package/types/register.d.ts +42 -0
- package/types/reply.d.ts +81 -0
- package/types/request.d.ts +95 -0
- package/types/route.d.ts +199 -0
- package/types/schema.d.ts +61 -0
- package/types/server-factory.d.ts +19 -0
- package/types/type-provider.d.ts +130 -0
- package/types/utils.d.ts +98 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const dns = require('node:dns')
|
|
4
|
+
const { networkInterfaces } = require('node:os')
|
|
5
|
+
const { test } = require('node:test')
|
|
6
|
+
const Fastify = require('..')
|
|
7
|
+
const undici = require('undici')
|
|
8
|
+
const proxyquire = require('proxyquire')
|
|
9
|
+
|
|
10
|
+
const isIPv6Missing = !Object.values(networkInterfaces()).flat().some(({ family }) => family === 'IPv6')
|
|
11
|
+
|
|
12
|
+
test('listen should accept null port', async t => {
|
|
13
|
+
const fastify = Fastify()
|
|
14
|
+
t.after(() => fastify.close())
|
|
15
|
+
|
|
16
|
+
await t.assert.doesNotReject(
|
|
17
|
+
fastify.listen({ port: null })
|
|
18
|
+
)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('listen should accept undefined port', async t => {
|
|
22
|
+
const fastify = Fastify()
|
|
23
|
+
t.after(() => fastify.close())
|
|
24
|
+
|
|
25
|
+
await t.assert.doesNotReject(
|
|
26
|
+
fastify.listen({ port: undefined })
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('listen should accept stringified number port', async t => {
|
|
31
|
+
const fastify = Fastify()
|
|
32
|
+
t.after(() => fastify.close())
|
|
33
|
+
|
|
34
|
+
await t.assert.doesNotReject(
|
|
35
|
+
fastify.listen({ port: '1234' })
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('listen should accept log text resolution function', async t => {
|
|
40
|
+
const fastify = Fastify()
|
|
41
|
+
t.after(() => fastify.close())
|
|
42
|
+
|
|
43
|
+
await t.assert.doesNotReject(
|
|
44
|
+
fastify.listen({
|
|
45
|
+
host: '127.0.0.1',
|
|
46
|
+
port: '1234',
|
|
47
|
+
listenTextResolver: (address) => {
|
|
48
|
+
t.assert.strictEqual(address, 'http://127.0.0.1:1234')
|
|
49
|
+
return 'hardcoded text'
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('listen should reject string port', async (t) => {
|
|
56
|
+
const fastify = Fastify()
|
|
57
|
+
t.after(() => fastify.close())
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
await fastify.listen({ port: 'hello-world' })
|
|
61
|
+
} catch (error) {
|
|
62
|
+
t.assert.strictEqual(error.code, 'ERR_SOCKET_BAD_PORT')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await fastify.listen({ port: '1234hello' })
|
|
67
|
+
} catch (error) {
|
|
68
|
+
t.assert.strictEqual(error.code, 'ERR_SOCKET_BAD_PORT')
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('Test for hostname and port', async (t) => {
|
|
73
|
+
t.plan(3)
|
|
74
|
+
const app = Fastify()
|
|
75
|
+
t.after(() => app.close())
|
|
76
|
+
app.get('/host', (req, res) => {
|
|
77
|
+
t.assert.strictEqual(req.host, 'localhost:8000')
|
|
78
|
+
t.assert.strictEqual(req.hostname, 'localhost')
|
|
79
|
+
t.assert.strictEqual(req.port, 8000)
|
|
80
|
+
res.send('ok')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
await app.listen({ port: 8000 })
|
|
84
|
+
await fetch('http://localhost:8000/host')
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('Test for IPV6 port', { skip: isIPv6Missing }, async (t) => {
|
|
88
|
+
t.plan(3)
|
|
89
|
+
const app = Fastify()
|
|
90
|
+
t.after(() => app.close())
|
|
91
|
+
app.get('/host', (req, res) => {
|
|
92
|
+
t.assert.strictEqual(req.host, '[::1]:3040')
|
|
93
|
+
t.assert.strictEqual(req.hostname, '[::1]')
|
|
94
|
+
t.assert.strictEqual(req.port, 3040)
|
|
95
|
+
res.send('ok')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
await app.listen({
|
|
99
|
+
port: 3040,
|
|
100
|
+
host: '::1'
|
|
101
|
+
})
|
|
102
|
+
await fetch('http://[::1]:3040/host')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('abort signal', async t => {
|
|
106
|
+
await t.test('should close server when aborted after', (t, end) => {
|
|
107
|
+
t.plan(2)
|
|
108
|
+
function onClose (instance, done) {
|
|
109
|
+
t.assert.strictEqual(instance, fastify)
|
|
110
|
+
done()
|
|
111
|
+
end()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const controller = new AbortController()
|
|
115
|
+
|
|
116
|
+
const fastify = Fastify()
|
|
117
|
+
fastify.addHook('onClose', onClose)
|
|
118
|
+
fastify.listen({ port: 1234, signal: controller.signal }, (err) => {
|
|
119
|
+
t.assert.ifError(err)
|
|
120
|
+
controller.abort()
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
await t.test('should close server when aborted after - promise', async (t) => {
|
|
125
|
+
t.plan(2)
|
|
126
|
+
const resolver = {}
|
|
127
|
+
resolver.promise = new Promise(function (resolve) {
|
|
128
|
+
resolver.resolve = resolve
|
|
129
|
+
})
|
|
130
|
+
function onClose (instance, done) {
|
|
131
|
+
t.assert.strictEqual(instance, fastify)
|
|
132
|
+
done()
|
|
133
|
+
resolver.resolve()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const controller = new AbortController()
|
|
137
|
+
|
|
138
|
+
const fastify = Fastify()
|
|
139
|
+
fastify.addHook('onClose', onClose)
|
|
140
|
+
const address = await fastify.listen({ port: 1234, signal: controller.signal })
|
|
141
|
+
t.assert.ok(address)
|
|
142
|
+
controller.abort()
|
|
143
|
+
await resolver.promise
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
await t.test('should close server when aborted during fastify.ready - promise', async (t) => {
|
|
147
|
+
t.plan(2)
|
|
148
|
+
const resolver = {}
|
|
149
|
+
resolver.promise = new Promise(function (resolve) {
|
|
150
|
+
resolver.resolve = resolve
|
|
151
|
+
})
|
|
152
|
+
function onClose (instance, done) {
|
|
153
|
+
t.assert.strictEqual(instance, fastify)
|
|
154
|
+
done()
|
|
155
|
+
resolver.resolve()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const controller = new AbortController()
|
|
159
|
+
|
|
160
|
+
const fastify = Fastify()
|
|
161
|
+
fastify.addHook('onClose', onClose)
|
|
162
|
+
const promise = fastify.listen({ port: 1234, signal: controller.signal })
|
|
163
|
+
controller.abort()
|
|
164
|
+
const address = await promise
|
|
165
|
+
// since the main server is not listening yet, or will not listen
|
|
166
|
+
// it should return undefined
|
|
167
|
+
t.assert.strictEqual(address, undefined)
|
|
168
|
+
await resolver.promise
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
await t.test('should close server when aborted during dns.lookup - promise', async (t) => {
|
|
172
|
+
t.plan(2)
|
|
173
|
+
const Fastify = proxyquire('..', {
|
|
174
|
+
'./lib/server.js': proxyquire('../lib/server.js', {
|
|
175
|
+
'node:dns': {
|
|
176
|
+
lookup: function (host, option, callback) {
|
|
177
|
+
controller.abort()
|
|
178
|
+
dns.lookup(host, option, callback)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
const resolver = {}
|
|
184
|
+
resolver.promise = new Promise(function (resolve) {
|
|
185
|
+
resolver.resolve = resolve
|
|
186
|
+
})
|
|
187
|
+
function onClose (instance, done) {
|
|
188
|
+
t.assert.strictEqual(instance, fastify)
|
|
189
|
+
done()
|
|
190
|
+
resolver.resolve()
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const controller = new AbortController()
|
|
194
|
+
|
|
195
|
+
const fastify = Fastify()
|
|
196
|
+
fastify.addHook('onClose', onClose)
|
|
197
|
+
const address = await fastify.listen({ port: 1234, signal: controller.signal })
|
|
198
|
+
// since the main server is already listening then close
|
|
199
|
+
// it should return address
|
|
200
|
+
t.assert.ok(address)
|
|
201
|
+
await resolver.promise
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
await t.test('should close server when aborted before', (t, end) => {
|
|
205
|
+
t.plan(1)
|
|
206
|
+
function onClose (instance, done) {
|
|
207
|
+
t.assert.strictEqual(instance, fastify)
|
|
208
|
+
done()
|
|
209
|
+
end()
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const controller = new AbortController()
|
|
213
|
+
controller.abort()
|
|
214
|
+
|
|
215
|
+
const fastify = Fastify()
|
|
216
|
+
fastify.addHook('onClose', onClose)
|
|
217
|
+
fastify.listen({ port: 1234, signal: controller.signal }, () => {
|
|
218
|
+
t.assert.fail('should not reach callback')
|
|
219
|
+
})
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
await t.test('should close server when aborted before - promise', async (t) => {
|
|
223
|
+
t.plan(2)
|
|
224
|
+
const resolver = {}
|
|
225
|
+
resolver.promise = new Promise(function (resolve) {
|
|
226
|
+
resolver.resolve = resolve
|
|
227
|
+
})
|
|
228
|
+
function onClose (instance, done) {
|
|
229
|
+
t.assert.strictEqual(instance, fastify)
|
|
230
|
+
done()
|
|
231
|
+
resolver.resolve()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const controller = new AbortController()
|
|
235
|
+
controller.abort()
|
|
236
|
+
|
|
237
|
+
const fastify = Fastify()
|
|
238
|
+
fastify.addHook('onClose', onClose)
|
|
239
|
+
const address = await fastify.listen({ port: 1234, signal: controller.signal })
|
|
240
|
+
t.assert.strictEqual(address, undefined) // ensure the API signature
|
|
241
|
+
await resolver.promise
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
await t.test('listen should not start server', (t, end) => {
|
|
245
|
+
t.plan(2)
|
|
246
|
+
function onClose (instance, done) {
|
|
247
|
+
t.assert.strictEqual(instance, fastify)
|
|
248
|
+
done()
|
|
249
|
+
end()
|
|
250
|
+
}
|
|
251
|
+
const controller = new AbortController()
|
|
252
|
+
|
|
253
|
+
const fastify = Fastify()
|
|
254
|
+
fastify.addHook('onClose', onClose)
|
|
255
|
+
fastify.listen({ port: 1234, signal: controller.signal }, (err) => {
|
|
256
|
+
t.assert.ifError(err)
|
|
257
|
+
})
|
|
258
|
+
controller.abort()
|
|
259
|
+
t.assert.strictEqual(fastify.server.listening, false)
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
await t.test('listen should not start server if already aborted', (t, end) => {
|
|
263
|
+
t.plan(2)
|
|
264
|
+
function onClose (instance, done) {
|
|
265
|
+
t.assert.strictEqual(instance, fastify)
|
|
266
|
+
done()
|
|
267
|
+
end()
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const controller = new AbortController()
|
|
271
|
+
controller.abort()
|
|
272
|
+
const fastify = Fastify()
|
|
273
|
+
fastify.addHook('onClose', onClose)
|
|
274
|
+
fastify.listen({ port: 1234, signal: controller.signal }, (err) => {
|
|
275
|
+
t.assert.ifError(err)
|
|
276
|
+
})
|
|
277
|
+
t.assert.strictEqual(fastify.server.listening, false)
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
await t.test('listen should throw if received invalid signal', t => {
|
|
281
|
+
t.plan(2)
|
|
282
|
+
const fastify = Fastify()
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
fastify.listen({ port: 1234, signal: {} }, (err) => {
|
|
286
|
+
t.assert.ifError(err)
|
|
287
|
+
})
|
|
288
|
+
t.assert.fail('should throw')
|
|
289
|
+
} catch (e) {
|
|
290
|
+
t.assert.strictEqual(e.code, 'FST_ERR_LISTEN_OPTIONS_INVALID')
|
|
291
|
+
t.assert.strictEqual(e.message, 'Invalid listen options: \'Invalid options.signal\'')
|
|
292
|
+
}
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
test('#5180 - preClose should be called before closing secondary server', async (t) => {
|
|
297
|
+
t.plan(2)
|
|
298
|
+
const fastify = Fastify({ forceCloseConnections: true })
|
|
299
|
+
let flag = false
|
|
300
|
+
t.after(() => fastify.close())
|
|
301
|
+
|
|
302
|
+
fastify.addHook('preClose', () => {
|
|
303
|
+
flag = true
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
fastify.get('/', async (req, reply) => {
|
|
307
|
+
// request will be pending for 1 second to simulate a slow request
|
|
308
|
+
await new Promise((resolve) => { setTimeout(resolve, 1000) })
|
|
309
|
+
return { hello: 'world' }
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
fastify.listen({ port: 0 }, (err) => {
|
|
313
|
+
t.assert.ifError(err)
|
|
314
|
+
const addresses = fastify.addresses()
|
|
315
|
+
const mainServerAddress = fastify.server.address()
|
|
316
|
+
let secondaryAddress
|
|
317
|
+
for (const addr of addresses) {
|
|
318
|
+
if (addr.family !== mainServerAddress.family) {
|
|
319
|
+
secondaryAddress = addr
|
|
320
|
+
secondaryAddress.address = secondaryAddress.family === 'IPv6'
|
|
321
|
+
? `[${secondaryAddress.address}]`
|
|
322
|
+
: secondaryAddress.address
|
|
323
|
+
break
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (!secondaryAddress) {
|
|
328
|
+
t.assert.ok(true, 'Secondary address not found')
|
|
329
|
+
return
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
undici.request(`http://${secondaryAddress.address}:${secondaryAddress.port}/`)
|
|
333
|
+
.then(
|
|
334
|
+
() => { t.assert.fail('Request should not succeed') },
|
|
335
|
+
() => {
|
|
336
|
+
t.assert.ok(flag)
|
|
337
|
+
}
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
// Close the server while the slow request is pending
|
|
341
|
+
setTimeout(fastify.close, 250)
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
// Wait 1000ms to ensure that the test is finished and async operations are
|
|
345
|
+
// completed
|
|
346
|
+
await new Promise((resolve) => { setTimeout(resolve, 1000) })
|
|
347
|
+
})
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const Fastify = require('..')
|
|
5
|
+
const { FST_ERR_ERROR_HANDLER_NOT_FN, FST_ERR_ERROR_HANDLER_ALREADY_SET } = require('../lib/errors')
|
|
6
|
+
|
|
7
|
+
test('setErrorHandler should throw an error if the handler is not a function', t => {
|
|
8
|
+
t.plan(1)
|
|
9
|
+
const fastify = Fastify()
|
|
10
|
+
|
|
11
|
+
t.assert.throws(() => fastify.setErrorHandler('not a function'), new FST_ERR_ERROR_HANDLER_NOT_FN())
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('setErrorHandler can be set independently in parent and child scopes', async t => {
|
|
15
|
+
t.plan(1)
|
|
16
|
+
|
|
17
|
+
const fastify = Fastify()
|
|
18
|
+
|
|
19
|
+
t.assert.doesNotThrow(() => {
|
|
20
|
+
fastify.setErrorHandler(() => {})
|
|
21
|
+
fastify.register(async (child) => {
|
|
22
|
+
child.setErrorHandler(() => {})
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('setErrorHandler can be overridden if allowErrorHandlerOverride is set to true', async t => {
|
|
28
|
+
t.plan(2)
|
|
29
|
+
|
|
30
|
+
const fastify = Fastify()
|
|
31
|
+
t.after(() => fastify.close())
|
|
32
|
+
|
|
33
|
+
fastify.register(async (child) => {
|
|
34
|
+
child.setErrorHandler(() => {})
|
|
35
|
+
t.assert.doesNotThrow(() => child.setErrorHandler(() => {}))
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
fastify.setErrorHandler(() => {})
|
|
39
|
+
t.assert.doesNotThrow(() => fastify.setErrorHandler(() => {}))
|
|
40
|
+
|
|
41
|
+
await fastify.ready()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('if `allowErrorHandlerOverride` is disabled, setErrorHandler should throw if called more than once in the same scope', t => {
|
|
45
|
+
t.plan(1)
|
|
46
|
+
|
|
47
|
+
const fastify = Fastify({
|
|
48
|
+
allowErrorHandlerOverride: false
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
fastify.setErrorHandler(() => {})
|
|
52
|
+
t.assert.throws(() => fastify.setErrorHandler(() => {}), new FST_ERR_ERROR_HANDLER_ALREADY_SET())
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('if `allowErrorHandlerOverride` is disabled, setErrorHandler should throw if called more than once in the same scope 2', async t => {
|
|
56
|
+
t.plan(1)
|
|
57
|
+
|
|
58
|
+
const fastify = Fastify({
|
|
59
|
+
allowErrorHandlerOverride: false
|
|
60
|
+
})
|
|
61
|
+
t.after(() => fastify.close())
|
|
62
|
+
|
|
63
|
+
fastify.register(async (child) => {
|
|
64
|
+
child.setErrorHandler(() => {})
|
|
65
|
+
t.assert.throws(() => child.setErrorHandler(() => {}), new FST_ERR_ERROR_HANDLER_ALREADY_SET())
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
await fastify.ready()
|
|
69
|
+
})
|