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,123 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const Fastify = require('../..')
|
|
5
|
+
const statusCodes = require('node:http').STATUS_CODES
|
|
6
|
+
const diagnostics = require('node:diagnostics_channel')
|
|
7
|
+
|
|
8
|
+
test('diagnostics channel error event should report correct status code', async (t) => {
|
|
9
|
+
t.plan(3)
|
|
10
|
+
const fastify = Fastify()
|
|
11
|
+
t.after(() => fastify.close())
|
|
12
|
+
|
|
13
|
+
let diagnosticsStatusCode
|
|
14
|
+
|
|
15
|
+
const channel = diagnostics.channel('tracing:fastify.request.handler:error')
|
|
16
|
+
const handler = (msg) => {
|
|
17
|
+
diagnosticsStatusCode = msg.reply.statusCode
|
|
18
|
+
}
|
|
19
|
+
channel.subscribe(handler)
|
|
20
|
+
t.after(() => channel.unsubscribe(handler))
|
|
21
|
+
|
|
22
|
+
fastify.get('/', async () => {
|
|
23
|
+
const err = new Error('test error')
|
|
24
|
+
err.statusCode = 503
|
|
25
|
+
throw err
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const res = await fastify.inject('/')
|
|
29
|
+
|
|
30
|
+
t.assert.strictEqual(res.statusCode, 503)
|
|
31
|
+
t.assert.strictEqual(diagnosticsStatusCode, 503, 'diagnostics channel should report correct status code')
|
|
32
|
+
t.assert.strictEqual(diagnosticsStatusCode, res.statusCode, 'diagnostics status should match response status')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('diagnostics channel error event should report 500 for errors without status', async (t) => {
|
|
36
|
+
t.plan(3)
|
|
37
|
+
const fastify = Fastify()
|
|
38
|
+
t.after(() => fastify.close())
|
|
39
|
+
|
|
40
|
+
let diagnosticsStatusCode
|
|
41
|
+
|
|
42
|
+
const channel = diagnostics.channel('tracing:fastify.request.handler:error')
|
|
43
|
+
const handler = (msg) => {
|
|
44
|
+
diagnosticsStatusCode = msg.reply.statusCode
|
|
45
|
+
}
|
|
46
|
+
channel.subscribe(handler)
|
|
47
|
+
t.after(() => channel.unsubscribe(handler))
|
|
48
|
+
|
|
49
|
+
fastify.get('/', async () => {
|
|
50
|
+
throw new Error('plain error without status')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const res = await fastify.inject('/')
|
|
54
|
+
|
|
55
|
+
t.assert.strictEqual(res.statusCode, 500)
|
|
56
|
+
t.assert.strictEqual(diagnosticsStatusCode, 500, 'diagnostics channel should report 500 for plain errors')
|
|
57
|
+
t.assert.strictEqual(diagnosticsStatusCode, res.statusCode, 'diagnostics status should match response status')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('diagnostics channel error event should report correct status with custom error handler', async (t) => {
|
|
61
|
+
t.plan(3)
|
|
62
|
+
const fastify = Fastify()
|
|
63
|
+
t.after(() => fastify.close())
|
|
64
|
+
|
|
65
|
+
let diagnosticsStatusCode
|
|
66
|
+
|
|
67
|
+
const channel = diagnostics.channel('tracing:fastify.request.handler:error')
|
|
68
|
+
const handler = (msg) => {
|
|
69
|
+
diagnosticsStatusCode = msg.reply.statusCode
|
|
70
|
+
}
|
|
71
|
+
channel.subscribe(handler)
|
|
72
|
+
t.after(() => channel.unsubscribe(handler))
|
|
73
|
+
|
|
74
|
+
fastify.setErrorHandler((error, request, reply) => {
|
|
75
|
+
reply.status(503).send({ error: error.message })
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
fastify.get('/', async () => {
|
|
79
|
+
throw new Error('handler error')
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const res = await fastify.inject('/')
|
|
83
|
+
|
|
84
|
+
// Note: The diagnostics channel fires before the custom error handler runs,
|
|
85
|
+
// so it reports 500 (default) rather than 503 (set by custom handler).
|
|
86
|
+
// This is expected behavior - the error channel reports the initial error state.
|
|
87
|
+
t.assert.strictEqual(res.statusCode, 503)
|
|
88
|
+
t.assert.strictEqual(diagnosticsStatusCode, 500, 'diagnostics channel reports status before custom handler')
|
|
89
|
+
t.assert.notStrictEqual(diagnosticsStatusCode, res.statusCode, 'custom handler can change status after diagnostics')
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('Error.status property support', (t, done) => {
|
|
93
|
+
t.plan(4)
|
|
94
|
+
const fastify = Fastify()
|
|
95
|
+
t.after(() => fastify.close())
|
|
96
|
+
const err = new Error('winter is coming')
|
|
97
|
+
err.status = 418
|
|
98
|
+
|
|
99
|
+
diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
|
|
100
|
+
t.assert.strictEqual(msg.error.message, 'winter is coming')
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
fastify.get('/', () => {
|
|
104
|
+
return Promise.reject(err)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
fastify.inject({
|
|
108
|
+
method: 'GET',
|
|
109
|
+
url: '/'
|
|
110
|
+
}, (error, res) => {
|
|
111
|
+
t.assert.ifError(error)
|
|
112
|
+
t.assert.strictEqual(res.statusCode, 418)
|
|
113
|
+
t.assert.deepStrictEqual(
|
|
114
|
+
{
|
|
115
|
+
error: statusCodes['418'],
|
|
116
|
+
message: err.message,
|
|
117
|
+
statusCode: 418
|
|
118
|
+
},
|
|
119
|
+
JSON.parse(res.payload)
|
|
120
|
+
)
|
|
121
|
+
done()
|
|
122
|
+
})
|
|
123
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const proxyquire = require('proxyquire')
|
|
5
|
+
|
|
6
|
+
test('diagnostics_channel when present and subscribers', t => {
|
|
7
|
+
t.plan(3)
|
|
8
|
+
|
|
9
|
+
let fastifyInHook
|
|
10
|
+
|
|
11
|
+
const diagnostics = {
|
|
12
|
+
channel (name) {
|
|
13
|
+
t.assert.strictEqual(name, 'fastify.initialization')
|
|
14
|
+
return {
|
|
15
|
+
hasSubscribers: true,
|
|
16
|
+
publish (event) {
|
|
17
|
+
t.assert.ok(event.fastify)
|
|
18
|
+
fastifyInHook = event.fastify
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
'@noCallThru': true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const fastify = proxyquire('../../fastify', {
|
|
26
|
+
'node:diagnostics_channel': diagnostics
|
|
27
|
+
})()
|
|
28
|
+
t.assert.strictEqual(fastifyInHook, fastify)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('diagnostics_channel when present and no subscribers', t => {
|
|
32
|
+
t.plan(1)
|
|
33
|
+
|
|
34
|
+
const diagnostics = {
|
|
35
|
+
channel (name) {
|
|
36
|
+
t.assert.strictEqual(name, 'fastify.initialization')
|
|
37
|
+
return {
|
|
38
|
+
hasSubscribers: false,
|
|
39
|
+
publish () {
|
|
40
|
+
t.assert.fail('publish should not be called')
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
'@noCallThru': true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
proxyquire('../../fastify', {
|
|
48
|
+
'node:diagnostics_channel': diagnostics
|
|
49
|
+
})()
|
|
50
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const diagnostics = require('node:diagnostics_channel')
|
|
5
|
+
const Fastify = require('../..')
|
|
6
|
+
const Request = require('../../lib/request')
|
|
7
|
+
const Reply = require('../../lib/reply')
|
|
8
|
+
|
|
9
|
+
test('diagnostics channel sync events fire in expected order', async t => {
|
|
10
|
+
t.plan(10)
|
|
11
|
+
let callOrder = 0
|
|
12
|
+
let firstEncounteredMessage
|
|
13
|
+
|
|
14
|
+
diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
|
|
15
|
+
t.assert.strictEqual(callOrder++, 0)
|
|
16
|
+
firstEncounteredMessage = msg
|
|
17
|
+
t.assert.ok(msg.request instanceof Request)
|
|
18
|
+
t.assert.ok(msg.reply instanceof Reply)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
|
|
22
|
+
t.assert.ok(msg.request instanceof Request)
|
|
23
|
+
t.assert.ok(msg.reply instanceof Reply)
|
|
24
|
+
t.assert.strictEqual(callOrder++, 1)
|
|
25
|
+
t.assert.strictEqual(msg, firstEncounteredMessage)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
|
|
29
|
+
t.assert.fail('should not trigger error channel')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const fastify = Fastify()
|
|
33
|
+
fastify.route({
|
|
34
|
+
method: 'GET',
|
|
35
|
+
url: '/',
|
|
36
|
+
handler: function (req, reply) {
|
|
37
|
+
setImmediate(() => reply.send({ hello: 'world' }))
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
t.after(() => { fastify.close() })
|
|
42
|
+
|
|
43
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
44
|
+
|
|
45
|
+
const result = await fetch(fastifyServer + '/')
|
|
46
|
+
t.assert.ok(result.ok)
|
|
47
|
+
t.assert.strictEqual(result.status, 200)
|
|
48
|
+
t.assert.deepStrictEqual(await result.json(), { hello: 'world' })
|
|
49
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const diagnostics = require('node:diagnostics_channel')
|
|
5
|
+
const Fastify = require('../..')
|
|
6
|
+
const Request = require('../../lib/request')
|
|
7
|
+
const Reply = require('../../lib/reply')
|
|
8
|
+
|
|
9
|
+
test('diagnostics channel sync events fire in expected order', async t => {
|
|
10
|
+
t.plan(10)
|
|
11
|
+
let callOrder = 0
|
|
12
|
+
let firstEncounteredMessage
|
|
13
|
+
|
|
14
|
+
diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
|
|
15
|
+
t.assert.strictEqual(callOrder++, 0)
|
|
16
|
+
firstEncounteredMessage = msg
|
|
17
|
+
t.assert.ok(msg.request instanceof Request)
|
|
18
|
+
t.assert.ok(msg.reply instanceof Reply)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
|
|
22
|
+
t.assert.ok(msg.request instanceof Request)
|
|
23
|
+
t.assert.ok(msg.reply instanceof Reply)
|
|
24
|
+
t.assert.strictEqual(callOrder++, 1)
|
|
25
|
+
t.assert.strictEqual(msg, firstEncounteredMessage)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
|
|
29
|
+
t.assert.fail('should not trigger error channel')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const fastify = Fastify()
|
|
33
|
+
fastify.route({
|
|
34
|
+
method: 'GET',
|
|
35
|
+
url: '/',
|
|
36
|
+
handler: function (req, reply) {
|
|
37
|
+
reply.send({ hello: 'world' })
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
42
|
+
t.after(() => { fastify.close() })
|
|
43
|
+
|
|
44
|
+
const response = await fetch(fastifyServer, {
|
|
45
|
+
method: 'GET'
|
|
46
|
+
})
|
|
47
|
+
t.assert.ok(response.ok)
|
|
48
|
+
t.assert.strictEqual(response.status, 200)
|
|
49
|
+
const body = await response.text()
|
|
50
|
+
t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
|
|
51
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const diagnostics = require('node:diagnostics_channel')
|
|
5
|
+
const Fastify = require('../..')
|
|
6
|
+
const Request = require('../../lib/request')
|
|
7
|
+
const Reply = require('../../lib/reply')
|
|
8
|
+
|
|
9
|
+
test('diagnostics channel sync events fire in expected order', async t => {
|
|
10
|
+
t.plan(13)
|
|
11
|
+
let callOrder = 0
|
|
12
|
+
let firstEncounteredMessage
|
|
13
|
+
|
|
14
|
+
diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
|
|
15
|
+
t.assert.strictEqual(callOrder++, 0)
|
|
16
|
+
firstEncounteredMessage = msg
|
|
17
|
+
t.assert.ok(msg.request instanceof Request)
|
|
18
|
+
t.assert.ok(msg.reply instanceof Reply)
|
|
19
|
+
t.assert.ok(msg.route)
|
|
20
|
+
t.assert.strictEqual(msg.route.url, '/:id')
|
|
21
|
+
t.assert.strictEqual(msg.route.method, 'GET')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
|
|
25
|
+
t.assert.ok(msg.request instanceof Request)
|
|
26
|
+
t.assert.ok(msg.reply instanceof Reply)
|
|
27
|
+
t.assert.strictEqual(callOrder++, 1)
|
|
28
|
+
t.assert.strictEqual(msg, firstEncounteredMessage)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
|
|
32
|
+
t.assert.fail('should not trigger error channel')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const fastify = Fastify()
|
|
36
|
+
fastify.route({
|
|
37
|
+
method: 'GET',
|
|
38
|
+
url: '/:id',
|
|
39
|
+
handler: function (req, reply) {
|
|
40
|
+
return { hello: 'world' }
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
45
|
+
t.after(() => { fastify.close() })
|
|
46
|
+
|
|
47
|
+
const response = await fetch(fastifyServer + '/7', {
|
|
48
|
+
method: 'GET'
|
|
49
|
+
})
|
|
50
|
+
t.assert.ok(response.ok)
|
|
51
|
+
t.assert.strictEqual(response.status, 200)
|
|
52
|
+
const body = await response.text()
|
|
53
|
+
t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
|
|
54
|
+
})
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const Fastify = require('..')
|
|
5
|
+
const fp = require('fastify-plugin')
|
|
6
|
+
|
|
7
|
+
test('encapsulates an child logger factory', async t => {
|
|
8
|
+
t.plan(4)
|
|
9
|
+
|
|
10
|
+
const fastify = Fastify()
|
|
11
|
+
fastify.register(async function (fastify) {
|
|
12
|
+
fastify.setChildLoggerFactory(function pluginFactory (logger, bindings, opts) {
|
|
13
|
+
const child = logger.child(bindings, opts)
|
|
14
|
+
child.customLog = function (message) {
|
|
15
|
+
t.assert.strictEqual(message, 'custom')
|
|
16
|
+
}
|
|
17
|
+
return child
|
|
18
|
+
})
|
|
19
|
+
fastify.get('/encapsulated', async (req) => {
|
|
20
|
+
req.log.customLog('custom')
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
fastify.setChildLoggerFactory(function globalFactory (logger, bindings, opts) {
|
|
25
|
+
const child = logger.child(bindings, opts)
|
|
26
|
+
child.globalLog = function (message) {
|
|
27
|
+
t.assert.strictEqual(message, 'global')
|
|
28
|
+
}
|
|
29
|
+
return child
|
|
30
|
+
})
|
|
31
|
+
fastify.get('/not-encapsulated', async (req) => {
|
|
32
|
+
req.log.globalLog('global')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const res1 = await fastify.inject('/encapsulated')
|
|
36
|
+
t.assert.strictEqual(res1.statusCode, 200)
|
|
37
|
+
|
|
38
|
+
const res2 = await fastify.inject('/not-encapsulated')
|
|
39
|
+
t.assert.strictEqual(res2.statusCode, 200)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('child logger factory set on root scope when using fastify-plugin', async t => {
|
|
43
|
+
t.plan(4)
|
|
44
|
+
|
|
45
|
+
const fastify = Fastify()
|
|
46
|
+
fastify.register(fp(async function (fastify) {
|
|
47
|
+
// Using fastify-plugin, the factory should be set on the root scope
|
|
48
|
+
fastify.setChildLoggerFactory(function pluginFactory (logger, bindings, opts) {
|
|
49
|
+
const child = logger.child(bindings, opts)
|
|
50
|
+
child.customLog = function (message) {
|
|
51
|
+
t.assert.strictEqual(message, 'custom')
|
|
52
|
+
}
|
|
53
|
+
return child
|
|
54
|
+
})
|
|
55
|
+
fastify.get('/not-encapsulated-1', async (req) => {
|
|
56
|
+
req.log.customLog('custom')
|
|
57
|
+
})
|
|
58
|
+
}))
|
|
59
|
+
|
|
60
|
+
fastify.get('/not-encapsulated-2', async (req) => {
|
|
61
|
+
req.log.customLog('custom')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const res1 = await fastify.inject('/not-encapsulated-1')
|
|
65
|
+
t.assert.strictEqual(res1.statusCode, 200)
|
|
66
|
+
|
|
67
|
+
const res2 = await fastify.inject('/not-encapsulated-2')
|
|
68
|
+
t.assert.strictEqual(res2.statusCode, 200)
|
|
69
|
+
})
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const Fastify = require('..')
|
|
5
|
+
|
|
6
|
+
// Because of how error handlers wrap things, following the control flow can be tricky
|
|
7
|
+
// In this test file numbered comments indicate the order statements are expected to execute
|
|
8
|
+
|
|
9
|
+
test('encapsulates an asynchronous error handler', async t => {
|
|
10
|
+
t.plan(3)
|
|
11
|
+
|
|
12
|
+
const fastify = Fastify()
|
|
13
|
+
fastify.register(async function (fastify) {
|
|
14
|
+
fastify.setErrorHandler(async function a (err) {
|
|
15
|
+
// 3. the inner error handler catches the error, and throws a new error
|
|
16
|
+
t.assert.strictEqual(err.message, 'from_endpoint')
|
|
17
|
+
throw new Error('from_inner')
|
|
18
|
+
})
|
|
19
|
+
fastify.get('/encapsulated', async () => {
|
|
20
|
+
// 2. the endpoint throws an error
|
|
21
|
+
throw new Error('from_endpoint')
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
fastify.setErrorHandler(async function b (err) {
|
|
26
|
+
// 4. the outer error handler catches the error thrown by the inner error handler
|
|
27
|
+
t.assert.strictEqual(err.message, 'from_inner')
|
|
28
|
+
// 5. the outer error handler throws a new error
|
|
29
|
+
throw new Error('from_outer')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// 1. the endpoint is called
|
|
33
|
+
const res = await fastify.inject('/encapsulated')
|
|
34
|
+
// 6. the default error handler returns the error from the outer error handler
|
|
35
|
+
t.assert.strictEqual(res.json().message, 'from_outer')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// See discussion in https://github.com/fastify/fastify/pull/5222#discussion_r1432573655
|
|
39
|
+
test('encapsulates a synchronous error handler', async t => {
|
|
40
|
+
t.plan(3)
|
|
41
|
+
|
|
42
|
+
const fastify = Fastify()
|
|
43
|
+
fastify.register(async function (fastify) {
|
|
44
|
+
fastify.setErrorHandler(function a (err) {
|
|
45
|
+
// 3. the inner error handler catches the error, and throws a new error
|
|
46
|
+
t.assert.strictEqual(err.message, 'from_endpoint')
|
|
47
|
+
throw new Error('from_inner')
|
|
48
|
+
})
|
|
49
|
+
fastify.get('/encapsulated', async () => {
|
|
50
|
+
// 2. the endpoint throws an error
|
|
51
|
+
throw new Error('from_endpoint')
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
fastify.setErrorHandler(async function b (err) {
|
|
56
|
+
// 4. the outer error handler catches the error thrown by the inner error handler
|
|
57
|
+
t.assert.strictEqual(err.message, 'from_inner')
|
|
58
|
+
// 5. the outer error handler throws a new error
|
|
59
|
+
throw new Error('from_outer')
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// 1. the endpoint is called
|
|
63
|
+
const res = await fastify.inject('/encapsulated')
|
|
64
|
+
// 6. the default error handler returns the error from the outer error handler
|
|
65
|
+
t.assert.strictEqual(res.json().message, 'from_outer')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('onError hook nested', async t => {
|
|
69
|
+
t.plan(4)
|
|
70
|
+
|
|
71
|
+
const fastify = Fastify()
|
|
72
|
+
fastify.register(async function (fastify) {
|
|
73
|
+
fastify.setErrorHandler(async function a (err) {
|
|
74
|
+
// 4. the inner error handler catches the error, and throws a new error
|
|
75
|
+
t.assert.strictEqual(err.message, 'from_endpoint')
|
|
76
|
+
throw new Error('from_inner')
|
|
77
|
+
})
|
|
78
|
+
fastify.get('/encapsulated', async () => {
|
|
79
|
+
// 2. the endpoint throws an error
|
|
80
|
+
throw new Error('from_endpoint')
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
fastify.setErrorHandler(async function b (err) {
|
|
85
|
+
// 5. the outer error handler catches the error thrown by the inner error handler
|
|
86
|
+
t.assert.strictEqual(err.message, 'from_inner')
|
|
87
|
+
// 6. the outer error handler throws a new error
|
|
88
|
+
throw new Error('from_outer')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
fastify.addHook('onError', async function (request, reply, err) {
|
|
92
|
+
// 3. the hook receives the error
|
|
93
|
+
t.assert.strictEqual(err.message, 'from_endpoint')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// 1. the endpoint is called
|
|
97
|
+
const res = await fastify.inject('/encapsulated')
|
|
98
|
+
// 7. the default error handler returns the error from the outer error handler
|
|
99
|
+
t.assert.strictEqual(res.json().message, 'from_outer')
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// See https://github.com/fastify/fastify/issues/5220
|
|
103
|
+
test('encapuslates an error handler, for errors thrown in hooks', async t => {
|
|
104
|
+
t.plan(3)
|
|
105
|
+
|
|
106
|
+
const fastify = Fastify()
|
|
107
|
+
fastify.register(async function (fastify) {
|
|
108
|
+
fastify.setErrorHandler(function a (err) {
|
|
109
|
+
// 3. the inner error handler catches the error, and throws a new error
|
|
110
|
+
t.assert.strictEqual(err.message, 'from_hook')
|
|
111
|
+
throw new Error('from_inner')
|
|
112
|
+
})
|
|
113
|
+
fastify.addHook('onRequest', async () => {
|
|
114
|
+
// 2. the hook throws an error
|
|
115
|
+
throw new Error('from_hook')
|
|
116
|
+
})
|
|
117
|
+
fastify.get('/encapsulated', async () => {})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
fastify.setErrorHandler(function b (err) {
|
|
121
|
+
// 4. the outer error handler catches the error thrown by the inner error handler
|
|
122
|
+
t.assert.strictEqual(err.message, 'from_inner')
|
|
123
|
+
// 5. the outer error handler throws a new error
|
|
124
|
+
throw new Error('from_outer')
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// 1. the endpoint is called
|
|
128
|
+
const res = await fastify.inject('/encapsulated')
|
|
129
|
+
// 6. the default error handler returns the error from the outer error handler
|
|
130
|
+
t.assert.strictEqual(res.json().message, 'from_outer')
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// See https://github.com/fastify/fastify/issues/5220
|
|
134
|
+
test('encapuslates many synchronous error handlers that rethrow errors', async t => {
|
|
135
|
+
const DEPTH = 100
|
|
136
|
+
t.plan(DEPTH + 2)
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* This creates a very nested set of error handlers, that looks like:
|
|
140
|
+
* plugin
|
|
141
|
+
* - error handler
|
|
142
|
+
* - plugin
|
|
143
|
+
* - error handler
|
|
144
|
+
* - plugin
|
|
145
|
+
* ... {to DEPTH levels}
|
|
146
|
+
* - plugin
|
|
147
|
+
* - error handler
|
|
148
|
+
* - GET /encapsulated
|
|
149
|
+
*/
|
|
150
|
+
const createNestedRoutes = (fastify, depth) => {
|
|
151
|
+
if (depth < 0) {
|
|
152
|
+
throw new Error('Expected depth >= 0')
|
|
153
|
+
} else if (depth === 0) {
|
|
154
|
+
fastify.setErrorHandler(function a (err) {
|
|
155
|
+
// 3. innermost error handler catches the error, and throws a new error
|
|
156
|
+
t.assert.strictEqual(err.message, 'from_route')
|
|
157
|
+
throw new Error(`from_handler_${depth}`)
|
|
158
|
+
})
|
|
159
|
+
fastify.get('/encapsulated', async () => {
|
|
160
|
+
// 2. the endpoint throws an error
|
|
161
|
+
throw new Error('from_route')
|
|
162
|
+
})
|
|
163
|
+
} else {
|
|
164
|
+
fastify.setErrorHandler(function d (err) {
|
|
165
|
+
// 4 to {DEPTH+4}. error handlers each catch errors, and then throws a new error
|
|
166
|
+
t.assert.strictEqual(err.message, `from_handler_${depth - 1}`)
|
|
167
|
+
throw new Error(`from_handler_${depth}`)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
fastify.register(async function (fastify) {
|
|
171
|
+
createNestedRoutes(fastify, depth - 1)
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const fastify = Fastify()
|
|
177
|
+
createNestedRoutes(fastify, DEPTH)
|
|
178
|
+
|
|
179
|
+
// 1. the endpoint is called
|
|
180
|
+
const res = await fastify.inject('/encapsulated')
|
|
181
|
+
// {DEPTH+5}. the default error handler returns the error from the outermost error handler
|
|
182
|
+
t.assert.strictEqual(res.json().message, `from_handler_${DEPTH}`)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// See https://github.com/fastify/fastify/issues/5220
|
|
186
|
+
// This was not failing previously, but we want to make sure the behavior continues to work in the same way across async and sync handlers
|
|
187
|
+
// Plus, the current setup is somewhat fragile to tweaks to wrapThenable as that's what retries (by calling res.send(err) again)
|
|
188
|
+
test('encapuslates many asynchronous error handlers that rethrow errors', async t => {
|
|
189
|
+
const DEPTH = 100
|
|
190
|
+
t.plan(DEPTH + 2)
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* This creates a very nested set of error handlers, that looks like:
|
|
194
|
+
* plugin
|
|
195
|
+
* - error handler
|
|
196
|
+
* - plugin
|
|
197
|
+
* - error handler
|
|
198
|
+
* - plugin
|
|
199
|
+
* ... {to DEPTH levels}
|
|
200
|
+
* - plugin
|
|
201
|
+
* - error handler
|
|
202
|
+
* - GET /encapsulated
|
|
203
|
+
*/
|
|
204
|
+
const createNestedRoutes = (fastify, depth) => {
|
|
205
|
+
if (depth < 0) {
|
|
206
|
+
throw new Error('Expected depth >= 0')
|
|
207
|
+
} else if (depth === 0) {
|
|
208
|
+
fastify.setErrorHandler(async function a (err) {
|
|
209
|
+
// 3. innermost error handler catches the error, and throws a new error
|
|
210
|
+
t.assert.strictEqual(err.message, 'from_route')
|
|
211
|
+
throw new Error(`from_handler_${depth}`)
|
|
212
|
+
})
|
|
213
|
+
fastify.get('/encapsulated', async () => {
|
|
214
|
+
// 2. the endpoint throws an error
|
|
215
|
+
throw new Error('from_route')
|
|
216
|
+
})
|
|
217
|
+
} else {
|
|
218
|
+
fastify.setErrorHandler(async function m (err) {
|
|
219
|
+
// 4 to {DEPTH+4}. error handlers each catch errors, and then throws a new error
|
|
220
|
+
t.assert.strictEqual(err.message, `from_handler_${depth - 1}`)
|
|
221
|
+
throw new Error(`from_handler_${depth}`)
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
fastify.register(async function (fastify) {
|
|
225
|
+
createNestedRoutes(fastify, depth - 1)
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const fastify = Fastify()
|
|
231
|
+
createNestedRoutes(fastify, DEPTH)
|
|
232
|
+
|
|
233
|
+
// 1. the endpoint is called
|
|
234
|
+
const res = await fastify.inject('/encapsulated')
|
|
235
|
+
// {DEPTH+5}. the default error handler returns the error from the outermost error handler
|
|
236
|
+
t.assert.strictEqual(res.json().message, `from_handler_${DEPTH}`)
|
|
237
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { errorCodes } from '../../fastify.js'
|
|
2
|
+
import { test } from 'node:test'
|
|
3
|
+
|
|
4
|
+
test('errorCodes in ESM', async t => {
|
|
5
|
+
// test a custom fastify error using errorCodes with ESM
|
|
6
|
+
const customError = errorCodes.FST_ERR_VALIDATION('custom error message')
|
|
7
|
+
t.assert.ok(typeof customError !== 'undefined')
|
|
8
|
+
t.assert.ok(customError instanceof errorCodes.FST_ERR_VALIDATION)
|
|
9
|
+
t.assert.strictEqual(customError.message, 'custom error message')
|
|
10
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import Fastify from '../../fastify.js'
|
|
3
|
+
|
|
4
|
+
test('esm support', async t => {
|
|
5
|
+
const fastify = Fastify()
|
|
6
|
+
|
|
7
|
+
fastify.register(import('./plugin.mjs'), { foo: 'bar' })
|
|
8
|
+
fastify.register(import('./other.mjs'))
|
|
9
|
+
|
|
10
|
+
await fastify.ready()
|
|
11
|
+
|
|
12
|
+
t.assert.strictEqual(fastify.foo, 'bar')
|
|
13
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import { fastify } from '../../fastify.js'
|
|
3
|
+
|
|
4
|
+
// This test is executed in index.test.js
|
|
5
|
+
test('named exports support', async t => {
|
|
6
|
+
const app = fastify()
|
|
7
|
+
|
|
8
|
+
app.register(import('./plugin.mjs'), { foo: 'bar' })
|
|
9
|
+
app.register(import('./other.mjs'))
|
|
10
|
+
|
|
11
|
+
await app.ready()
|
|
12
|
+
|
|
13
|
+
t.assert.strictEqual(app.foo, 'bar')
|
|
14
|
+
})
|