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,616 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const Fastify = require('../fastify')
|
|
5
|
+
const fs = require('node:fs')
|
|
6
|
+
const { Readable } = require('node:stream')
|
|
7
|
+
const { fetch: undiciFetch } = require('undici')
|
|
8
|
+
const http = require('node:http')
|
|
9
|
+
const { setTimeout: sleep } = require('node:timers/promises')
|
|
10
|
+
|
|
11
|
+
test('should response with a ReadableStream', async (t) => {
|
|
12
|
+
t.plan(2)
|
|
13
|
+
|
|
14
|
+
const fastify = Fastify()
|
|
15
|
+
|
|
16
|
+
fastify.get('/', function (request, reply) {
|
|
17
|
+
const stream = fs.createReadStream(__filename)
|
|
18
|
+
reply.code(200).send(Readable.toWeb(stream))
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
statusCode,
|
|
23
|
+
body
|
|
24
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
25
|
+
|
|
26
|
+
const expected = await fs.promises.readFile(__filename)
|
|
27
|
+
|
|
28
|
+
t.assert.strictEqual(statusCode, 200)
|
|
29
|
+
t.assert.strictEqual(expected.toString(), body.toString())
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('should response with a Response', async (t) => {
|
|
33
|
+
t.plan(3)
|
|
34
|
+
|
|
35
|
+
const fastify = Fastify()
|
|
36
|
+
|
|
37
|
+
fastify.get('/', function (request, reply) {
|
|
38
|
+
const stream = fs.createReadStream(__filename)
|
|
39
|
+
reply.send(new Response(Readable.toWeb(stream), {
|
|
40
|
+
status: 200,
|
|
41
|
+
headers: {
|
|
42
|
+
hello: 'world'
|
|
43
|
+
}
|
|
44
|
+
}))
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const {
|
|
48
|
+
statusCode,
|
|
49
|
+
headers,
|
|
50
|
+
body
|
|
51
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
52
|
+
|
|
53
|
+
const expected = await fs.promises.readFile(__filename)
|
|
54
|
+
|
|
55
|
+
t.assert.strictEqual(statusCode, 200)
|
|
56
|
+
t.assert.strictEqual(expected.toString(), body.toString())
|
|
57
|
+
t.assert.strictEqual(headers.hello, 'world')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('should response with a Response 204', async (t) => {
|
|
61
|
+
t.plan(3)
|
|
62
|
+
|
|
63
|
+
const fastify = Fastify()
|
|
64
|
+
|
|
65
|
+
fastify.get('/', function (request, reply) {
|
|
66
|
+
reply.send(new Response(null, {
|
|
67
|
+
status: 204,
|
|
68
|
+
headers: {
|
|
69
|
+
hello: 'world'
|
|
70
|
+
}
|
|
71
|
+
}))
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const {
|
|
75
|
+
statusCode,
|
|
76
|
+
headers,
|
|
77
|
+
body
|
|
78
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
79
|
+
|
|
80
|
+
t.assert.strictEqual(statusCode, 204)
|
|
81
|
+
t.assert.strictEqual(body, '')
|
|
82
|
+
t.assert.strictEqual(headers.hello, 'world')
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('should response with a Response 304', async (t) => {
|
|
86
|
+
t.plan(3)
|
|
87
|
+
|
|
88
|
+
const fastify = Fastify()
|
|
89
|
+
|
|
90
|
+
fastify.get('/', function (request, reply) {
|
|
91
|
+
reply.send(new Response(null, {
|
|
92
|
+
status: 304,
|
|
93
|
+
headers: {
|
|
94
|
+
hello: 'world'
|
|
95
|
+
}
|
|
96
|
+
}))
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const {
|
|
100
|
+
statusCode,
|
|
101
|
+
headers,
|
|
102
|
+
body
|
|
103
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
104
|
+
|
|
105
|
+
t.assert.strictEqual(statusCode, 304)
|
|
106
|
+
t.assert.strictEqual(body, '')
|
|
107
|
+
t.assert.strictEqual(headers.hello, 'world')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('should response with a Response without body', async (t) => {
|
|
111
|
+
t.plan(3)
|
|
112
|
+
|
|
113
|
+
const fastify = Fastify()
|
|
114
|
+
|
|
115
|
+
fastify.get('/', function (request, reply) {
|
|
116
|
+
reply.send(new Response(null, {
|
|
117
|
+
status: 200,
|
|
118
|
+
headers: {
|
|
119
|
+
hello: 'world'
|
|
120
|
+
}
|
|
121
|
+
}))
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
const {
|
|
125
|
+
statusCode,
|
|
126
|
+
headers,
|
|
127
|
+
body
|
|
128
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
129
|
+
|
|
130
|
+
t.assert.strictEqual(statusCode, 200)
|
|
131
|
+
t.assert.strictEqual(body, '')
|
|
132
|
+
t.assert.strictEqual(headers.hello, 'world')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('able to use in onSend hook - ReadableStream', async (t) => {
|
|
136
|
+
t.plan(4)
|
|
137
|
+
|
|
138
|
+
const fastify = Fastify()
|
|
139
|
+
|
|
140
|
+
fastify.get('/', function (request, reply) {
|
|
141
|
+
const stream = fs.createReadStream(__filename)
|
|
142
|
+
reply.code(500).send(Readable.toWeb(stream))
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
fastify.addHook('onSend', (request, reply, payload, done) => {
|
|
146
|
+
t.assert.strictEqual(Object.prototype.toString.call(payload), '[object ReadableStream]')
|
|
147
|
+
done(null, new Response(payload, {
|
|
148
|
+
status: 200,
|
|
149
|
+
headers: {
|
|
150
|
+
hello: 'world'
|
|
151
|
+
}
|
|
152
|
+
}))
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const {
|
|
156
|
+
statusCode,
|
|
157
|
+
headers,
|
|
158
|
+
body
|
|
159
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
160
|
+
|
|
161
|
+
const expected = await fs.promises.readFile(__filename)
|
|
162
|
+
|
|
163
|
+
t.assert.strictEqual(statusCode, 200)
|
|
164
|
+
t.assert.strictEqual(expected.toString(), body.toString())
|
|
165
|
+
t.assert.strictEqual(headers.hello, 'world')
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('able to use in onSend hook - Response', async (t) => {
|
|
169
|
+
t.plan(4)
|
|
170
|
+
|
|
171
|
+
const fastify = Fastify()
|
|
172
|
+
|
|
173
|
+
fastify.get('/', function (request, reply) {
|
|
174
|
+
const stream = fs.createReadStream(__filename)
|
|
175
|
+
reply.send(new Response(Readable.toWeb(stream), {
|
|
176
|
+
status: 500,
|
|
177
|
+
headers: {
|
|
178
|
+
hello: 'world'
|
|
179
|
+
}
|
|
180
|
+
}))
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
fastify.addHook('onSend', (request, reply, payload, done) => {
|
|
184
|
+
t.assert.strictEqual(Object.prototype.toString.call(payload), '[object Response]')
|
|
185
|
+
done(null, new Response(payload.body, {
|
|
186
|
+
status: 200,
|
|
187
|
+
headers: payload.headers
|
|
188
|
+
}))
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
const {
|
|
192
|
+
statusCode,
|
|
193
|
+
headers,
|
|
194
|
+
body
|
|
195
|
+
} = await fastify.inject({ method: 'GET', path: '/' })
|
|
196
|
+
|
|
197
|
+
const expected = await fs.promises.readFile(__filename)
|
|
198
|
+
|
|
199
|
+
t.assert.strictEqual(statusCode, 200)
|
|
200
|
+
t.assert.strictEqual(expected.toString(), body.toString())
|
|
201
|
+
t.assert.strictEqual(headers.hello, 'world')
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
test('Error when Response.bodyUsed', async (t) => {
|
|
205
|
+
t.plan(4)
|
|
206
|
+
|
|
207
|
+
const expected = await fs.promises.readFile(__filename)
|
|
208
|
+
|
|
209
|
+
const fastify = Fastify()
|
|
210
|
+
|
|
211
|
+
fastify.get('/', async function (request, reply) {
|
|
212
|
+
const stream = fs.createReadStream(__filename)
|
|
213
|
+
const response = new Response(Readable.toWeb(stream), {
|
|
214
|
+
status: 200,
|
|
215
|
+
headers: {
|
|
216
|
+
hello: 'world'
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
const file = await response.text()
|
|
220
|
+
t.assert.strictEqual(expected.toString(), file)
|
|
221
|
+
t.assert.strictEqual(response.bodyUsed, true)
|
|
222
|
+
return reply.send(response)
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
226
|
+
|
|
227
|
+
t.assert.strictEqual(response.statusCode, 500)
|
|
228
|
+
const body = response.json()
|
|
229
|
+
t.assert.strictEqual(body.code, 'FST_ERR_REP_RESPONSE_BODY_CONSUMED')
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
test('Error when Response.body.locked', async (t) => {
|
|
233
|
+
t.plan(3)
|
|
234
|
+
|
|
235
|
+
const fastify = Fastify()
|
|
236
|
+
|
|
237
|
+
fastify.get('/', async function (request, reply) {
|
|
238
|
+
const stream = Readable.toWeb(fs.createReadStream(__filename))
|
|
239
|
+
const response = new Response(stream, {
|
|
240
|
+
status: 200,
|
|
241
|
+
headers: {
|
|
242
|
+
hello: 'world'
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
stream.getReader()
|
|
246
|
+
t.assert.strictEqual(stream.locked, true)
|
|
247
|
+
return reply.send(response)
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
251
|
+
|
|
252
|
+
t.assert.strictEqual(response.statusCode, 500)
|
|
253
|
+
const body = response.json()
|
|
254
|
+
t.assert.strictEqual(body.code, 'FST_ERR_REP_READABLE_STREAM_LOCKED')
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
test('Error when ReadableStream.locked', async (t) => {
|
|
258
|
+
t.plan(3)
|
|
259
|
+
|
|
260
|
+
const fastify = Fastify()
|
|
261
|
+
|
|
262
|
+
fastify.get('/', async function (request, reply) {
|
|
263
|
+
const stream = Readable.toWeb(fs.createReadStream(__filename))
|
|
264
|
+
stream.getReader()
|
|
265
|
+
t.assert.strictEqual(stream.locked, true)
|
|
266
|
+
return reply.send(stream)
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
270
|
+
|
|
271
|
+
t.assert.strictEqual(response.statusCode, 500)
|
|
272
|
+
const body = response.json()
|
|
273
|
+
t.assert.strictEqual(body.code, 'FST_ERR_REP_READABLE_STREAM_LOCKED')
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
test('allow to pipe with fetch', async (t) => {
|
|
277
|
+
t.plan(2)
|
|
278
|
+
const abortController = new AbortController()
|
|
279
|
+
const { signal } = abortController
|
|
280
|
+
|
|
281
|
+
const fastify = Fastify()
|
|
282
|
+
t.after(() => {
|
|
283
|
+
fastify.close()
|
|
284
|
+
abortController.abort()
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
fastify.get('/', function (request, reply) {
|
|
288
|
+
return fetch(`${fastify.listeningOrigin}/fetch`, {
|
|
289
|
+
method: 'GET',
|
|
290
|
+
signal
|
|
291
|
+
})
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
fastify.get('/fetch', function async (request, reply) {
|
|
295
|
+
reply.code(200).send({ ok: true })
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
await fastify.listen()
|
|
299
|
+
|
|
300
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
301
|
+
|
|
302
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
303
|
+
t.assert.deepStrictEqual(response.json(), { ok: true })
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
test('allow to pipe with undici.fetch', async (t) => {
|
|
307
|
+
t.plan(2)
|
|
308
|
+
const abortController = new AbortController()
|
|
309
|
+
const { signal } = abortController
|
|
310
|
+
|
|
311
|
+
const fastify = Fastify()
|
|
312
|
+
t.after(() => {
|
|
313
|
+
fastify.close()
|
|
314
|
+
abortController.abort()
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
fastify.get('/', function (request, reply) {
|
|
318
|
+
return undiciFetch(`${fastify.listeningOrigin}/fetch`, {
|
|
319
|
+
method: 'GET',
|
|
320
|
+
signal
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
fastify.get('/fetch', function (request, reply) {
|
|
325
|
+
reply.code(200).send({ ok: true })
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
await fastify.listen()
|
|
329
|
+
|
|
330
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
331
|
+
|
|
332
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
333
|
+
t.assert.deepStrictEqual(response.json(), { ok: true })
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
test('WebStream error before headers sent should trigger error handler', async (t) => {
|
|
337
|
+
t.plan(2)
|
|
338
|
+
|
|
339
|
+
const fastify = Fastify()
|
|
340
|
+
|
|
341
|
+
fastify.get('/', function (request, reply) {
|
|
342
|
+
const stream = new ReadableStream({
|
|
343
|
+
start (controller) {
|
|
344
|
+
controller.error(new Error('stream error'))
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
reply.send(stream)
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
351
|
+
|
|
352
|
+
t.assert.strictEqual(response.statusCode, 500)
|
|
353
|
+
t.assert.strictEqual(response.json().message, 'stream error')
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
test('WebStream error after headers sent should destroy response', (t, done) => {
|
|
357
|
+
t.plan(2)
|
|
358
|
+
|
|
359
|
+
const fastify = Fastify()
|
|
360
|
+
t.after(() => fastify.close())
|
|
361
|
+
|
|
362
|
+
fastify.get('/', function (request, reply) {
|
|
363
|
+
const stream = new ReadableStream({
|
|
364
|
+
start (controller) {
|
|
365
|
+
controller.enqueue('hello')
|
|
366
|
+
},
|
|
367
|
+
pull (controller) {
|
|
368
|
+
setTimeout(() => {
|
|
369
|
+
controller.error(new Error('stream error'))
|
|
370
|
+
}, 10)
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
reply.header('content-type', 'text/plain').send(stream)
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
fastify.listen({ port: 0 }, err => {
|
|
377
|
+
t.assert.ifError(err)
|
|
378
|
+
|
|
379
|
+
let finished = false
|
|
380
|
+
http.get(`http://localhost:${fastify.server.address().port}`, (res) => {
|
|
381
|
+
res.on('close', () => {
|
|
382
|
+
if (!finished) {
|
|
383
|
+
finished = true
|
|
384
|
+
t.assert.ok('response closed')
|
|
385
|
+
done()
|
|
386
|
+
}
|
|
387
|
+
})
|
|
388
|
+
res.resume()
|
|
389
|
+
})
|
|
390
|
+
})
|
|
391
|
+
})
|
|
392
|
+
|
|
393
|
+
test('WebStream should cancel reader when response is destroyed', (t, done) => {
|
|
394
|
+
t.plan(2)
|
|
395
|
+
|
|
396
|
+
const fastify = Fastify()
|
|
397
|
+
t.after(() => fastify.close())
|
|
398
|
+
|
|
399
|
+
let readerCancelled = false
|
|
400
|
+
|
|
401
|
+
fastify.get('/', function (request, reply) {
|
|
402
|
+
const stream = new ReadableStream({
|
|
403
|
+
start (controller) {
|
|
404
|
+
controller.enqueue('hello')
|
|
405
|
+
},
|
|
406
|
+
pull (controller) {
|
|
407
|
+
return new Promise(() => {})
|
|
408
|
+
},
|
|
409
|
+
cancel () {
|
|
410
|
+
readerCancelled = true
|
|
411
|
+
}
|
|
412
|
+
})
|
|
413
|
+
reply.header('content-type', 'text/plain').send(stream)
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
fastify.listen({ port: 0 }, err => {
|
|
417
|
+
t.assert.ifError(err)
|
|
418
|
+
|
|
419
|
+
const req = http.get(`http://localhost:${fastify.server.address().port}`, (res) => {
|
|
420
|
+
res.once('data', () => {
|
|
421
|
+
req.destroy()
|
|
422
|
+
setTimeout(() => {
|
|
423
|
+
t.assert.strictEqual(readerCancelled, true)
|
|
424
|
+
done()
|
|
425
|
+
}, 50)
|
|
426
|
+
})
|
|
427
|
+
})
|
|
428
|
+
})
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
test('WebStream should respect backpressure', async (t) => {
|
|
432
|
+
t.plan(3)
|
|
433
|
+
|
|
434
|
+
const fastify = Fastify()
|
|
435
|
+
t.after(() => fastify.close())
|
|
436
|
+
|
|
437
|
+
let drainEmittedAt = 0
|
|
438
|
+
let secondWriteAt = 0
|
|
439
|
+
let resolveSecondWrite
|
|
440
|
+
const secondWrite = new Promise((resolve) => {
|
|
441
|
+
resolveSecondWrite = resolve
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
fastify.get('/', function (request, reply) {
|
|
445
|
+
const raw = reply.raw
|
|
446
|
+
const originalWrite = raw.write.bind(raw)
|
|
447
|
+
const bufferedChunks = []
|
|
448
|
+
let wroteFirstChunk = false
|
|
449
|
+
|
|
450
|
+
raw.once('drain', () => {
|
|
451
|
+
for (const bufferedChunk of bufferedChunks) {
|
|
452
|
+
originalWrite(bufferedChunk)
|
|
453
|
+
}
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
raw.write = function (chunk, encoding, cb) {
|
|
457
|
+
if (!wroteFirstChunk) {
|
|
458
|
+
wroteFirstChunk = true
|
|
459
|
+
bufferedChunks.push(Buffer.from(chunk))
|
|
460
|
+
sleep(100).then(() => {
|
|
461
|
+
drainEmittedAt = Date.now()
|
|
462
|
+
raw.emit('drain')
|
|
463
|
+
})
|
|
464
|
+
if (typeof cb === 'function') {
|
|
465
|
+
cb()
|
|
466
|
+
}
|
|
467
|
+
return false
|
|
468
|
+
}
|
|
469
|
+
if (!secondWriteAt) {
|
|
470
|
+
secondWriteAt = Date.now()
|
|
471
|
+
resolveSecondWrite()
|
|
472
|
+
}
|
|
473
|
+
return originalWrite(chunk, encoding, cb)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const stream = new ReadableStream({
|
|
477
|
+
start (controller) {
|
|
478
|
+
controller.enqueue(Buffer.from('chunk-1'))
|
|
479
|
+
},
|
|
480
|
+
pull (controller) {
|
|
481
|
+
controller.enqueue(Buffer.from('chunk-2'))
|
|
482
|
+
controller.close()
|
|
483
|
+
}
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
reply.header('content-type', 'text/plain').send(stream)
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
await fastify.listen({ port: 0 })
|
|
490
|
+
|
|
491
|
+
const response = await undiciFetch(`http://localhost:${fastify.server.address().port}/`)
|
|
492
|
+
const bodyPromise = response.text()
|
|
493
|
+
|
|
494
|
+
await secondWrite
|
|
495
|
+
await sleep(120)
|
|
496
|
+
const body = await bodyPromise
|
|
497
|
+
|
|
498
|
+
t.assert.strictEqual(response.status, 200)
|
|
499
|
+
t.assert.strictEqual(body, 'chunk-1chunk-2')
|
|
500
|
+
t.assert.ok(secondWriteAt >= drainEmittedAt)
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
test('WebStream should stop reading on drain after response destroy', async (t) => {
|
|
504
|
+
t.plan(2)
|
|
505
|
+
|
|
506
|
+
const fastify = Fastify()
|
|
507
|
+
t.after(() => fastify.close())
|
|
508
|
+
|
|
509
|
+
let cancelCalled = false
|
|
510
|
+
let resolveCancel
|
|
511
|
+
const cancelPromise = new Promise((resolve) => {
|
|
512
|
+
resolveCancel = resolve
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
fastify.get('/', function (request, reply) {
|
|
516
|
+
const raw = reply.raw
|
|
517
|
+
const originalWrite = raw.write.bind(raw)
|
|
518
|
+
let firstWrite = true
|
|
519
|
+
|
|
520
|
+
raw.write = function (chunk, encoding, cb) {
|
|
521
|
+
if (firstWrite) {
|
|
522
|
+
firstWrite = false
|
|
523
|
+
if (typeof cb === 'function') {
|
|
524
|
+
cb()
|
|
525
|
+
}
|
|
526
|
+
queueMicrotask(() => {
|
|
527
|
+
raw.destroy()
|
|
528
|
+
raw.emit('drain')
|
|
529
|
+
})
|
|
530
|
+
return false
|
|
531
|
+
}
|
|
532
|
+
return originalWrite(chunk, encoding, cb)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const stream = new ReadableStream({
|
|
536
|
+
start (controller) {
|
|
537
|
+
controller.enqueue(Buffer.from('chunk-1'))
|
|
538
|
+
},
|
|
539
|
+
pull (controller) {
|
|
540
|
+
controller.enqueue(Buffer.from('chunk-2'))
|
|
541
|
+
controller.close()
|
|
542
|
+
},
|
|
543
|
+
cancel () {
|
|
544
|
+
cancelCalled = true
|
|
545
|
+
resolveCancel()
|
|
546
|
+
}
|
|
547
|
+
})
|
|
548
|
+
|
|
549
|
+
reply.header('content-type', 'text/plain').send(stream)
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
await new Promise((resolve, reject) => {
|
|
553
|
+
fastify.listen({ port: 0 }, err => {
|
|
554
|
+
if (err) return reject(err)
|
|
555
|
+
resolve()
|
|
556
|
+
})
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
await new Promise((resolve, reject) => {
|
|
560
|
+
const req = http.get(`http://localhost:${fastify.server.address().port}/`, (res) => {
|
|
561
|
+
res.once('close', resolve)
|
|
562
|
+
res.resume()
|
|
563
|
+
})
|
|
564
|
+
req.once('error', (err) => {
|
|
565
|
+
if (err.code === 'ECONNRESET') {
|
|
566
|
+
resolve()
|
|
567
|
+
} else {
|
|
568
|
+
reject(err)
|
|
569
|
+
}
|
|
570
|
+
})
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
await cancelPromise
|
|
574
|
+
t.assert.ok(true, 'response interrupted as expected')
|
|
575
|
+
t.assert.strictEqual(cancelCalled, true)
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
test('WebStream should warn when headers already sent', async (t) => {
|
|
579
|
+
t.plan(2)
|
|
580
|
+
|
|
581
|
+
let warnCalled = false
|
|
582
|
+
const spyLogger = {
|
|
583
|
+
level: 'warn',
|
|
584
|
+
fatal: () => { },
|
|
585
|
+
error: () => { },
|
|
586
|
+
warn: (msg) => {
|
|
587
|
+
if (typeof msg === 'string' && msg.includes('use res.writeHead in stream mode')) {
|
|
588
|
+
warnCalled = true
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
info: () => { },
|
|
592
|
+
debug: () => { },
|
|
593
|
+
trace: () => { },
|
|
594
|
+
child: () => spyLogger
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const fastify = Fastify({ loggerInstance: spyLogger })
|
|
598
|
+
t.after(() => fastify.close())
|
|
599
|
+
|
|
600
|
+
fastify.get('/', function (request, reply) {
|
|
601
|
+
reply.raw.writeHead(200, { 'content-type': 'text/plain' })
|
|
602
|
+
const stream = new ReadableStream({
|
|
603
|
+
start (controller) {
|
|
604
|
+
controller.enqueue('hello')
|
|
605
|
+
controller.close()
|
|
606
|
+
}
|
|
607
|
+
})
|
|
608
|
+
reply.send(stream)
|
|
609
|
+
})
|
|
610
|
+
|
|
611
|
+
await fastify.listen({ port: 0 })
|
|
612
|
+
|
|
613
|
+
const response = await fetch(`http://localhost:${fastify.server.address().port}/`)
|
|
614
|
+
t.assert.strictEqual(response.status, 200)
|
|
615
|
+
t.assert.strictEqual(warnCalled, true)
|
|
616
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const { kReplyHijacked } = require('../lib/symbols')
|
|
5
|
+
const wrapThenable = require('../lib/wrap-thenable')
|
|
6
|
+
const Reply = require('../lib/reply')
|
|
7
|
+
|
|
8
|
+
test('should resolve immediately when reply[kReplyHijacked] is true', async t => {
|
|
9
|
+
await new Promise(resolve => {
|
|
10
|
+
const reply = {}
|
|
11
|
+
reply[kReplyHijacked] = true
|
|
12
|
+
const thenable = Promise.resolve()
|
|
13
|
+
wrapThenable(thenable, reply)
|
|
14
|
+
resolve()
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('should reject immediately when reply[kReplyHijacked] is true', t => {
|
|
19
|
+
t.plan(1)
|
|
20
|
+
const reply = new Reply({}, {}, {})
|
|
21
|
+
reply[kReplyHijacked] = true
|
|
22
|
+
reply.log = {
|
|
23
|
+
error: ({ err }) => {
|
|
24
|
+
t.assert.strictEqual(err.message, 'Reply sent already')
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const thenable = Promise.reject(new Error('Reply sent already'))
|
|
29
|
+
wrapThenable(thenable, reply)
|
|
30
|
+
})
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { RawServerBase, RawServerDefault, RawRequestDefaultExpression } from './utils'
|
|
2
|
+
import { FastifyRequest } from './request'
|
|
3
|
+
import { RouteGenericInterface } from './route'
|
|
4
|
+
import { FastifyTypeProvider, FastifyTypeProviderDefault } from './type-provider'
|
|
5
|
+
import { FastifySchema } from './schema'
|
|
6
|
+
|
|
7
|
+
type ContentTypeParserDoneFunction = (err: Error | null, body?: any) => void
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Body parser method that operators on request body
|
|
11
|
+
*/
|
|
12
|
+
export type FastifyBodyParser<
|
|
13
|
+
RawBody extends string | Buffer,
|
|
14
|
+
RawServer extends RawServerBase = RawServerDefault,
|
|
15
|
+
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
|
|
16
|
+
RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
|
|
17
|
+
SchemaCompiler extends FastifySchema = FastifySchema,
|
|
18
|
+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
19
|
+
> = ((request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>, rawBody: RawBody, done: ContentTypeParserDoneFunction) => void)
|
|
20
|
+
| ((request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>, rawBody: RawBody) => Promise<any>)
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Content Type Parser method that operates on request content
|
|
24
|
+
*/
|
|
25
|
+
export type FastifyContentTypeParser<
|
|
26
|
+
RawServer extends RawServerBase = RawServerDefault,
|
|
27
|
+
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
|
|
28
|
+
RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
|
|
29
|
+
SchemaCompiler extends FastifySchema = FastifySchema,
|
|
30
|
+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
31
|
+
> = ((request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>, payload: RawRequest) => Promise<any>)
|
|
32
|
+
| ((request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>, payload: RawRequest, done: ContentTypeParserDoneFunction) => void)
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Natively, Fastify only supports 'application/json' and 'text/plain' content types. The default charset is utf-8. If you need to support different content types, you can use the addContentTypeParser API. The default JSON and/or plain text parser can be changed.
|
|
36
|
+
*/
|
|
37
|
+
export interface AddContentTypeParser<
|
|
38
|
+
RawServer extends RawServerBase = RawServerDefault,
|
|
39
|
+
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
|
|
40
|
+
RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
|
|
41
|
+
SchemaCompiler extends FastifySchema = FastifySchema,
|
|
42
|
+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
43
|
+
> {
|
|
44
|
+
(
|
|
45
|
+
contentType: string | string[] | RegExp,
|
|
46
|
+
opts: {
|
|
47
|
+
bodyLimit?: number;
|
|
48
|
+
},
|
|
49
|
+
parser: FastifyContentTypeParser<RawServer, RawRequest, RouteGeneric, SchemaCompiler, TypeProvider>
|
|
50
|
+
): void;
|
|
51
|
+
(contentType: string | string[] | RegExp, parser: FastifyContentTypeParser<RawServer, RawRequest, RouteGeneric, SchemaCompiler, TypeProvider>): void;
|
|
52
|
+
<parseAs extends string | Buffer>(
|
|
53
|
+
contentType: string | string[] | RegExp,
|
|
54
|
+
opts: {
|
|
55
|
+
parseAs: parseAs extends Buffer ? 'buffer' : 'string';
|
|
56
|
+
bodyLimit?: number;
|
|
57
|
+
},
|
|
58
|
+
parser: FastifyBodyParser<parseAs, RawServer, RawRequest, RouteGeneric, SchemaCompiler, TypeProvider>
|
|
59
|
+
): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Checks for a type parser of a content type
|
|
64
|
+
*/
|
|
65
|
+
export type hasContentTypeParser = (contentType: string | RegExp) => boolean
|
|
66
|
+
|
|
67
|
+
export type ProtoAction = 'error' | 'remove' | 'ignore'
|
|
68
|
+
|
|
69
|
+
export type ConstructorAction = 'error' | 'remove' | 'ignore'
|
|
70
|
+
|
|
71
|
+
export type getDefaultJsonParser = (onProtoPoisoning: ProtoAction, onConstructorPoisoning: ConstructorAction) => FastifyBodyParser<string>
|
|
72
|
+
|
|
73
|
+
export type removeContentTypeParser = (contentType: string | RegExp | (string | RegExp)[]) => void
|
|
74
|
+
|
|
75
|
+
export type removeAllContentTypeParsers = () => void
|