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,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { createHook } = require('node:async_hooks')
|
|
4
|
+
const { test } = require('node:test')
|
|
5
|
+
const Fastify = require('..')
|
|
6
|
+
|
|
7
|
+
const remainingIds = new Set()
|
|
8
|
+
|
|
9
|
+
createHook({
|
|
10
|
+
init (asyncId, type, triggerAsyncId, resource) {
|
|
11
|
+
if (type === 'content-type-parser:run') {
|
|
12
|
+
remainingIds.add(asyncId)
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
destroy (asyncId) {
|
|
16
|
+
remainingIds.delete(asyncId)
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const app = Fastify({ logger: false })
|
|
21
|
+
|
|
22
|
+
test('test async hooks', async (t) => {
|
|
23
|
+
app.get('/', function (request, reply) {
|
|
24
|
+
reply.send({ id: 42 })
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
app.post('/', function (request, reply) {
|
|
28
|
+
reply.send({ id: 42 })
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
t.after(() => app.close())
|
|
32
|
+
|
|
33
|
+
const fastifyServer = await app.listen({ port: 0 })
|
|
34
|
+
|
|
35
|
+
const result1 = await fetch(fastifyServer, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' },
|
|
38
|
+
body: JSON.stringify({ hello: 'world' })
|
|
39
|
+
})
|
|
40
|
+
t.assert.strictEqual(result1.status, 200)
|
|
41
|
+
|
|
42
|
+
const result2 = await fetch(fastifyServer, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: { 'Content-Type': 'application/json' },
|
|
45
|
+
body: JSON.stringify({ hello: 'world' })
|
|
46
|
+
})
|
|
47
|
+
t.assert.strictEqual(result2.status, 200)
|
|
48
|
+
|
|
49
|
+
const result3 = await fetch(fastifyServer)
|
|
50
|
+
t.assert.strictEqual(result3.status, 200)
|
|
51
|
+
t.assert.strictEqual(remainingIds.size, 0)
|
|
52
|
+
})
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Fastify = require('../fastify')
|
|
4
|
+
const zlib = require('node:zlib')
|
|
5
|
+
const { test } = require('node:test')
|
|
6
|
+
|
|
7
|
+
test('bodyLimit', async t => {
|
|
8
|
+
t.plan(4)
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
Fastify({ bodyLimit: 1.3 })
|
|
12
|
+
t.assert.fail('option must be an integer')
|
|
13
|
+
} catch (err) {
|
|
14
|
+
t.assert.ok(err)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
Fastify({ bodyLimit: [] })
|
|
19
|
+
t.assert.fail('option must be an integer')
|
|
20
|
+
} catch (err) {
|
|
21
|
+
t.assert.ok(err)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const fastify = Fastify({ bodyLimit: 1 })
|
|
25
|
+
|
|
26
|
+
fastify.post('/', (request, reply) => {
|
|
27
|
+
reply.send({ error: 'handler should not be called' })
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
31
|
+
t.after(() => { fastify.close() })
|
|
32
|
+
|
|
33
|
+
const result = await fetch(fastifyServer, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
body: JSON.stringify([])
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
t.assert.ok(!result.ok)
|
|
40
|
+
t.assert.strictEqual(result.status, 413)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('bodyLimit is applied to decoded content', async (t) => {
|
|
44
|
+
t.plan(6)
|
|
45
|
+
|
|
46
|
+
const body = { x: 'x'.repeat(30000) }
|
|
47
|
+
const json = JSON.stringify(body)
|
|
48
|
+
const encoded = zlib.gzipSync(json)
|
|
49
|
+
|
|
50
|
+
const fastify = Fastify()
|
|
51
|
+
|
|
52
|
+
fastify.addHook('preParsing', async (req, reply, payload) => {
|
|
53
|
+
t.assert.strictEqual(req.headers['content-length'], `${encoded.length}`)
|
|
54
|
+
const unzip = zlib.createGunzip()
|
|
55
|
+
Object.defineProperty(unzip, 'receivedEncodedLength', {
|
|
56
|
+
get () {
|
|
57
|
+
return unzip.bytesWritten
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
payload.pipe(unzip)
|
|
61
|
+
return unzip
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
fastify.post('/body-limit-40k', {
|
|
65
|
+
bodyLimit: 40000,
|
|
66
|
+
onError: async (req, res, err) => {
|
|
67
|
+
t.fail('should not be called')
|
|
68
|
+
}
|
|
69
|
+
}, (request, reply) => {
|
|
70
|
+
reply.send({ x: request.body.x })
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
fastify.post('/body-limit-20k', {
|
|
74
|
+
bodyLimit: 20000,
|
|
75
|
+
onError: async (req, res, err) => {
|
|
76
|
+
t.assert.strictEqual(err.code, 'FST_ERR_CTP_BODY_TOO_LARGE')
|
|
77
|
+
t.assert.strictEqual(err.statusCode, 413)
|
|
78
|
+
}
|
|
79
|
+
}, (request, reply) => {
|
|
80
|
+
reply.send({ x: 'handler should not be called' })
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
await t.test('bodyLimit 40k', async (t) => {
|
|
84
|
+
const result = await fastify.inject({
|
|
85
|
+
method: 'POST',
|
|
86
|
+
url: '/body-limit-40k',
|
|
87
|
+
headers: {
|
|
88
|
+
'content-encoding': 'gzip',
|
|
89
|
+
'content-type': 'application/json'
|
|
90
|
+
},
|
|
91
|
+
payload: encoded
|
|
92
|
+
})
|
|
93
|
+
t.assert.strictEqual(result.statusCode, 200)
|
|
94
|
+
t.assert.deepStrictEqual(result.json(), body)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
await t.test('bodyLimit 20k', async (t) => {
|
|
98
|
+
const result = await fastify.inject({
|
|
99
|
+
method: 'POST',
|
|
100
|
+
url: '/body-limit-20k',
|
|
101
|
+
headers: {
|
|
102
|
+
'content-encoding': 'gzip',
|
|
103
|
+
'content-type': 'application/json'
|
|
104
|
+
},
|
|
105
|
+
payload: encoded
|
|
106
|
+
})
|
|
107
|
+
t.assert.strictEqual(result.statusCode, 413)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('default request.routeOptions.bodyLimit should be 1048576', async t => {
|
|
112
|
+
t.plan(3)
|
|
113
|
+
const fastify = Fastify()
|
|
114
|
+
fastify.post('/default-bodylimit', {
|
|
115
|
+
handler (request, reply) {
|
|
116
|
+
t.assert.strictEqual(1048576, request.routeOptions.bodyLimit)
|
|
117
|
+
reply.send({ })
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
121
|
+
t.after(() => { fastify.close() })
|
|
122
|
+
|
|
123
|
+
const result = await fetch(fastifyServer + '/default-bodylimit', {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
headers: { 'Content-Type': 'application/json' },
|
|
126
|
+
body: JSON.stringify([])
|
|
127
|
+
})
|
|
128
|
+
t.assert.ok(result.ok)
|
|
129
|
+
t.assert.strictEqual(result.status, 200)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('request.routeOptions.bodyLimit should be equal to route limit', async t => {
|
|
133
|
+
t.plan(3)
|
|
134
|
+
const fastify = Fastify({ bodyLimit: 1 })
|
|
135
|
+
fastify.post('/route-limit', {
|
|
136
|
+
bodyLimit: 1000,
|
|
137
|
+
handler (request, reply) {
|
|
138
|
+
t.assert.strictEqual(1000, request.routeOptions.bodyLimit)
|
|
139
|
+
reply.send({})
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
143
|
+
t.after(() => { fastify.close() })
|
|
144
|
+
|
|
145
|
+
const result = await fetch(fastifyServer + '/route-limit', {
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: { 'Content-Type': 'application/json' },
|
|
148
|
+
body: JSON.stringify([])
|
|
149
|
+
})
|
|
150
|
+
t.assert.ok(result.ok)
|
|
151
|
+
t.assert.strictEqual(result.status, 200)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('request.routeOptions.bodyLimit should be equal to server limit', async t => {
|
|
155
|
+
t.plan(3)
|
|
156
|
+
const fastify = Fastify({ bodyLimit: 100 })
|
|
157
|
+
fastify.post('/server-limit', {
|
|
158
|
+
handler (request, reply) {
|
|
159
|
+
t.assert.strictEqual(100, request.routeOptions.bodyLimit)
|
|
160
|
+
reply.send({})
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
164
|
+
t.after(() => { fastify.close() })
|
|
165
|
+
|
|
166
|
+
const result = await fetch(fastifyServer + '/server-limit', {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
headers: { 'Content-Type': 'application/json' },
|
|
169
|
+
body: JSON.stringify([])
|
|
170
|
+
})
|
|
171
|
+
t.assert.ok(result.ok)
|
|
172
|
+
t.assert.strictEqual(result.status, 200)
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
test('bodyLimit should use byte length for UTF-8 strings, not character length', async t => {
|
|
176
|
+
t.plan(4)
|
|
177
|
+
|
|
178
|
+
// Create a string with multi-byte UTF-8 characters
|
|
179
|
+
// Use Japanese characters that are 3 bytes each in UTF-8
|
|
180
|
+
const multiByteString = 'あああ' // 3 characters, 9 bytes in UTF-8
|
|
181
|
+
t.assert.strictEqual(multiByteString.length, 3) // 3 characters
|
|
182
|
+
t.assert.strictEqual(Buffer.byteLength(multiByteString, 'utf8'), 9) // 9 bytes
|
|
183
|
+
|
|
184
|
+
const fastify = Fastify()
|
|
185
|
+
|
|
186
|
+
// Add a custom text parser that returns the string as-is
|
|
187
|
+
fastify.addContentTypeParser('text/plain', { parseAs: 'string' }, (req, body, done) => {
|
|
188
|
+
done(null, body)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// Set body limit to 7 bytes - this should reject the string (9 bytes)
|
|
192
|
+
// even though string.length (3) would be under any reasonable limit
|
|
193
|
+
fastify.post('/test-utf8', {
|
|
194
|
+
bodyLimit: 7
|
|
195
|
+
}, (request, reply) => {
|
|
196
|
+
reply.send({ body: request.body, length: request.body.length })
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
await t.test('should reject body when byte length exceeds limit', async (t) => {
|
|
200
|
+
const result = await fastify.inject({
|
|
201
|
+
method: 'POST',
|
|
202
|
+
url: '/test-utf8',
|
|
203
|
+
headers: { 'Content-Type': 'text/plain', 'Content-Length': null },
|
|
204
|
+
payload: multiByteString
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
t.assert.strictEqual(result.statusCode, 413)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
await t.test('should accept body when byte length is within limit', async (t) => {
|
|
211
|
+
const smallString = 'あ' // 1 character, 3 bytes, under the 7 byte limit
|
|
212
|
+
|
|
213
|
+
const result = await fastify.inject({
|
|
214
|
+
method: 'POST',
|
|
215
|
+
url: '/test-utf8',
|
|
216
|
+
headers: { 'Content-Type': 'text/plain' },
|
|
217
|
+
payload: smallString
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
t.assert.strictEqual(result.statusCode, 200)
|
|
221
|
+
t.assert.strictEqual(result.json().body, smallString)
|
|
222
|
+
t.assert.strictEqual(result.json().length, 1) // 1 character
|
|
223
|
+
})
|
|
224
|
+
})
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const Fastify = require('..')
|
|
5
|
+
|
|
6
|
+
test('Buffer test', async t => {
|
|
7
|
+
const fastify = Fastify()
|
|
8
|
+
fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, fastify.getDefaultJsonParser('error', 'ignore'))
|
|
9
|
+
|
|
10
|
+
fastify.delete('/', async (request) => {
|
|
11
|
+
return request.body
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
await test('should return 200 if the body is not empty', async t => {
|
|
15
|
+
t.plan(3)
|
|
16
|
+
|
|
17
|
+
const response = await fastify.inject({
|
|
18
|
+
method: 'DELETE',
|
|
19
|
+
url: '/',
|
|
20
|
+
payload: Buffer.from('{"hello":"world"}'),
|
|
21
|
+
headers: {
|
|
22
|
+
'content-type': 'application/json'
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
t.assert.ifError(response.error)
|
|
27
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
28
|
+
t.assert.deepStrictEqual(response.payload.toString(), '{"hello":"world"}')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
await test('should return 400 if the body is empty', async t => {
|
|
32
|
+
t.plan(3)
|
|
33
|
+
|
|
34
|
+
const response = await fastify.inject({
|
|
35
|
+
method: 'DELETE',
|
|
36
|
+
url: '/',
|
|
37
|
+
payload: Buffer.alloc(0),
|
|
38
|
+
headers: {
|
|
39
|
+
'content-type': 'application/json'
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
t.assert.ifError(response.error)
|
|
44
|
+
t.assert.strictEqual(response.statusCode, 400)
|
|
45
|
+
t.assert.deepStrictEqual(JSON.parse(response.payload.toString()), {
|
|
46
|
+
error: 'Bad Request',
|
|
47
|
+
code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
|
48
|
+
message: 'Body cannot be empty when content-type is set to \'application/json\'',
|
|
49
|
+
statusCode: 400
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
await test('should return 400 if the body is invalid json', async t => {
|
|
54
|
+
t.plan(3)
|
|
55
|
+
|
|
56
|
+
const response = await fastify.inject({
|
|
57
|
+
method: 'DELETE',
|
|
58
|
+
url: '/',
|
|
59
|
+
payload: Buffer.from(']'),
|
|
60
|
+
headers: {
|
|
61
|
+
'content-type': 'application/json'
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
t.assert.ifError(response.error)
|
|
66
|
+
t.assert.strictEqual(response.statusCode, 400)
|
|
67
|
+
t.assert.deepStrictEqual(JSON.parse(response.payload.toString()), {
|
|
68
|
+
error: 'Bad Request',
|
|
69
|
+
code: 'FST_ERR_CTP_INVALID_JSON_BODY',
|
|
70
|
+
message: 'Body is not valid JSON but content-type is set to \'application/json\'',
|
|
71
|
+
statusCode: 400
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const fs = require('node:fs')
|
|
5
|
+
const path = require('node:path')
|
|
6
|
+
const { loadESLint } = require('eslint')
|
|
7
|
+
|
|
8
|
+
const { code } = require('../../build/build-error-serializer')
|
|
9
|
+
|
|
10
|
+
function unifyLineBreak (str) {
|
|
11
|
+
return str.toString().replace(/\r\n/g, '\n')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
test('check generated code syntax', async (t) => {
|
|
15
|
+
t.plan(1)
|
|
16
|
+
|
|
17
|
+
// standard is a esm, we import it like this
|
|
18
|
+
const Eslint = await loadESLint({ useFlatConfig: true })
|
|
19
|
+
const eslint = new Eslint()
|
|
20
|
+
const result = await eslint.lintText(code)
|
|
21
|
+
|
|
22
|
+
// if there are any invalid syntax
|
|
23
|
+
// fatal count will be greater than 0
|
|
24
|
+
t.assert.strictEqual(result[0].fatalErrorCount, 0)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const isPrepublish = !!process.env.PREPUBLISH
|
|
28
|
+
|
|
29
|
+
test('ensure the current error serializer is latest', { skip: !isPrepublish }, async (t) => {
|
|
30
|
+
t.plan(1)
|
|
31
|
+
|
|
32
|
+
const current = await fs.promises.readFile(path.resolve('lib/error-serializer.js'))
|
|
33
|
+
|
|
34
|
+
// line break should not be a problem depends on system
|
|
35
|
+
t.assert.strictEqual(unifyLineBreak(current), unifyLineBreak(code))
|
|
36
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
const { test } = require('node:test')
|
|
6
|
+
const fastify = require('../../fastify')()
|
|
7
|
+
|
|
8
|
+
test('should be the same as package.json', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
|
|
11
|
+
const json = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'package.json')).toString('utf8'))
|
|
12
|
+
|
|
13
|
+
t.assert.strictEqual(fastify.version, json.version)
|
|
14
|
+
})
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const os = require('node:os')
|
|
4
|
+
const forge = require('node-forge')
|
|
5
|
+
|
|
6
|
+
// from self-cert module
|
|
7
|
+
function selfCert (opts) {
|
|
8
|
+
const options = opts || {}
|
|
9
|
+
const log = opts.logger || require('abstract-logging')
|
|
10
|
+
const now = new Date()
|
|
11
|
+
|
|
12
|
+
if (!options.attrs) options.attrs = {}
|
|
13
|
+
if (!options.expires) {
|
|
14
|
+
options.expires = new Date(
|
|
15
|
+
now.getFullYear() + 5, now.getMonth() + 1, now.getDate()
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
log.debug('generating key pair')
|
|
20
|
+
const keys = forge.pki.rsa.generateKeyPair(options.bits || 2048)
|
|
21
|
+
log.debug('key pair generated')
|
|
22
|
+
|
|
23
|
+
log.debug('generating self-signed certificate')
|
|
24
|
+
const cert = forge.pki.createCertificate()
|
|
25
|
+
cert.publicKey = keys.publicKey
|
|
26
|
+
cert.serialNumber = '01'
|
|
27
|
+
cert.validity.notBefore = now
|
|
28
|
+
cert.validity.notAfter = options.expires
|
|
29
|
+
|
|
30
|
+
const attrs = [
|
|
31
|
+
{ name: 'commonName', value: options.attrs.commonName || os.hostname() },
|
|
32
|
+
{ name: 'countryName', value: options.attrs.countryName || 'US' },
|
|
33
|
+
{ name: 'stateOrProvinceName', value: options.attrs.stateName || 'Georgia' },
|
|
34
|
+
{ name: 'localityName', value: options.attrs.locality || 'Atlanta' },
|
|
35
|
+
{ name: 'organizationName', value: options.attrs.orgName || 'None' },
|
|
36
|
+
{ shortName: 'OU', value: options.attrs.shortName || 'example' }
|
|
37
|
+
]
|
|
38
|
+
cert.setSubject(attrs)
|
|
39
|
+
cert.setIssuer(attrs)
|
|
40
|
+
|
|
41
|
+
cert.setExtensions([
|
|
42
|
+
{ name: 'basicConstraints', cA: true },
|
|
43
|
+
{
|
|
44
|
+
name: 'keyUsage',
|
|
45
|
+
keyCertSign: true,
|
|
46
|
+
digitalSignature: true,
|
|
47
|
+
nonRepudiation: true,
|
|
48
|
+
keyEncipherment: true,
|
|
49
|
+
dataEncipherment: true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'extKeyUsage',
|
|
53
|
+
serverAuth: true,
|
|
54
|
+
clientAuth: true,
|
|
55
|
+
codeSigning: true,
|
|
56
|
+
emailProtection: true,
|
|
57
|
+
timeStamping: true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'nsCertType',
|
|
61
|
+
client: true,
|
|
62
|
+
server: true,
|
|
63
|
+
email: true,
|
|
64
|
+
objsign: true,
|
|
65
|
+
sslCA: true,
|
|
66
|
+
emailCA: true,
|
|
67
|
+
objCA: true
|
|
68
|
+
},
|
|
69
|
+
{ name: 'subjectKeyIdentifier' },
|
|
70
|
+
{
|
|
71
|
+
name: 'subjectAltName',
|
|
72
|
+
altNames: [{ type: 6 /* URI */, value: 'DNS: ' + attrs[0].value }].concat((function () {
|
|
73
|
+
const interfaces = os.networkInterfaces()
|
|
74
|
+
|
|
75
|
+
// fix citgm: skip invalid ips (aix72-ppc64)
|
|
76
|
+
const ips = Object.values(interfaces).flat()
|
|
77
|
+
.filter(i => !!forge.util.bytesFromIP(i.address))
|
|
78
|
+
.map(i => ({ type: 7 /* IP */, ip: i.address }))
|
|
79
|
+
|
|
80
|
+
return ips
|
|
81
|
+
}()))
|
|
82
|
+
}
|
|
83
|
+
])
|
|
84
|
+
|
|
85
|
+
cert.sign(keys.privateKey)
|
|
86
|
+
log.debug('certificate generated')
|
|
87
|
+
return {
|
|
88
|
+
privateKey: forge.pki.privateKeyToPem(keys.privateKey),
|
|
89
|
+
publicKey: forge.pki.publicKeyToPem(keys.publicKey),
|
|
90
|
+
certificate: forge.pki.certificateToPem(cert)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function buildCertificate () {
|
|
95
|
+
// "global" is used in here because "t.context" is only supported by "t.beforeEach" and "t.afterEach"
|
|
96
|
+
// For the test case which execute this code which will be using `t.before` and it can reduce the
|
|
97
|
+
// number of times executing it.
|
|
98
|
+
if (!global.context || !global.context.cert || !global.context.key) {
|
|
99
|
+
const certs = selfCert({
|
|
100
|
+
expires: new Date(Date.now() + 86400000)
|
|
101
|
+
})
|
|
102
|
+
global.context = {
|
|
103
|
+
cert: certs.certificate,
|
|
104
|
+
key: certs.privateKey
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = { buildCertificate }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Bundlers test stack
|
|
2
|
+
|
|
3
|
+
In some cases, developers bundle their apps for several targets such as serverless applications.
|
|
4
|
+
Even if it's not recommended by Fastify team; we need to ensure we do not break the build process.
|
|
5
|
+
Please note this might result in features behaving differently, like the version handling check for plugins.
|
|
6
|
+
|
|
7
|
+
## Test bundlers
|
|
8
|
+
|
|
9
|
+
The bundler test stack has been defined separately from the rest of the Unit testing stack because it's not a
|
|
10
|
+
part of the fastify lib itself. Note that the tests run in CI only on NodeJs LTS version.
|
|
11
|
+
Developers do not need to install every bundler to run unit tests.
|
|
12
|
+
|
|
13
|
+
To run the bundler tests you will need to install the repository dependencies followed by the bundler
|
|
14
|
+
stack dependencies. See:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# path: root of repository /fastify
|
|
18
|
+
npm i
|
|
19
|
+
cd test/bundler/webpack
|
|
20
|
+
npm i
|
|
21
|
+
npm run test # test command runs bundle before of starting the test
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Bundler test development
|
|
25
|
+
|
|
26
|
+
To not break the fastify unit testing stack please name test files like this `*-test.js` and not `*.test.js`,
|
|
27
|
+
otherwise it will be targeted by the regular expression used for unit tests for fastify.
|
|
28
|
+
Tests need to ensure the build process works and the fastify application can be run,
|
|
29
|
+
no need to go in deep testing unless an issue is raised.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const fastifySuccess = require('./dist/success')
|
|
5
|
+
const fastifyFailPlugin = require('./dist/failPlugin')
|
|
6
|
+
|
|
7
|
+
test('Bundled package should work', (t, done) => {
|
|
8
|
+
t.plan(4)
|
|
9
|
+
fastifySuccess.ready((err) => {
|
|
10
|
+
t.assert.ifError(err)
|
|
11
|
+
fastifySuccess.inject(
|
|
12
|
+
{
|
|
13
|
+
method: 'GET',
|
|
14
|
+
url: '/'
|
|
15
|
+
},
|
|
16
|
+
(error, res) => {
|
|
17
|
+
t.assert.ifError(error)
|
|
18
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
19
|
+
t.assert.deepStrictEqual(res.json(), { hello: 'world' })
|
|
20
|
+
done()
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('Bundled package should not work with bad plugin version', (t, done) => {
|
|
27
|
+
t.plan(1)
|
|
28
|
+
fastifyFailPlugin.ready((err) => {
|
|
29
|
+
t.assert.match(err.message, /expected '9.x' fastify version/i)
|
|
30
|
+
done()
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1",
|
|
3
|
+
"scripts": {
|
|
4
|
+
"bundle": "esbuild success=src/index.js failPlugin=src/fail-plugin-version.js --bundle --outdir=dist --platform=node",
|
|
5
|
+
"test": "npm run bundle && node bundler-test.js"
|
|
6
|
+
},
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"esbuild": "^0.25.0"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fp = require('fastify-plugin')
|
|
4
|
+
const fastify = require('../../../../')()
|
|
5
|
+
|
|
6
|
+
fastify.get('/', function (request, reply) {
|
|
7
|
+
reply.send({ hello: 'world' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
fastify.register(fp((instance, opts, done) => {
|
|
11
|
+
done()
|
|
12
|
+
}, { fastify: '9.x' }))
|
|
13
|
+
|
|
14
|
+
module.exports = fastify
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const fastifySuccess = require('./dist/success')
|
|
5
|
+
const fastifyFailPlugin = require('./dist/failPlugin')
|
|
6
|
+
|
|
7
|
+
test('Bundled package should work', (t, done) => {
|
|
8
|
+
t.plan(4)
|
|
9
|
+
fastifySuccess.ready((err) => {
|
|
10
|
+
t.assert.ifError(err)
|
|
11
|
+
fastifySuccess.inject(
|
|
12
|
+
{
|
|
13
|
+
method: 'GET',
|
|
14
|
+
url: '/'
|
|
15
|
+
},
|
|
16
|
+
(error, res) => {
|
|
17
|
+
t.assert.ifError(error)
|
|
18
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
19
|
+
t.assert.deepStrictEqual(res.json(), { hello: 'world' })
|
|
20
|
+
done()
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('Bundled package should not work with bad plugin version', (t, done) => {
|
|
27
|
+
t.plan(1)
|
|
28
|
+
fastifyFailPlugin.ready((err) => {
|
|
29
|
+
t.assert.match(err.message, /expected '9.x' fastify version/i)
|
|
30
|
+
done()
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fp = require('fastify-plugin')
|
|
4
|
+
const fastify = require('../../../../')()
|
|
5
|
+
|
|
6
|
+
fastify.get('/', function (request, reply) {
|
|
7
|
+
reply.send({ hello: 'world' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
fastify.register(fp((instance, opts, done) => {
|
|
11
|
+
done()
|
|
12
|
+
}, { fastify: '9.x' }))
|
|
13
|
+
|
|
14
|
+
module.exports = fastify
|