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,352 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
|
|
5
|
+
const Ajv = require('ajv')
|
|
6
|
+
const ajv = new Ajv({ coerceTypes: true })
|
|
7
|
+
|
|
8
|
+
const validation = require('../../lib/validation')
|
|
9
|
+
const { normalizeSchema } = require('../../lib/schemas')
|
|
10
|
+
const symbols = require('../../lib/validation').symbols
|
|
11
|
+
const { kSchemaVisited } = require('../../lib/symbols')
|
|
12
|
+
|
|
13
|
+
test('Symbols', t => {
|
|
14
|
+
t.plan(5)
|
|
15
|
+
t.assert.strictEqual(typeof symbols.responseSchema, 'symbol')
|
|
16
|
+
t.assert.strictEqual(typeof symbols.bodySchema, 'symbol')
|
|
17
|
+
t.assert.strictEqual(typeof symbols.querystringSchema, 'symbol')
|
|
18
|
+
t.assert.strictEqual(typeof symbols.paramsSchema, 'symbol')
|
|
19
|
+
t.assert.strictEqual(typeof symbols.headersSchema, 'symbol')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
;['compileSchemasForValidation',
|
|
23
|
+
'compileSchemasForSerialization'].forEach(func => {
|
|
24
|
+
test(`${func} schema - missing schema`, t => {
|
|
25
|
+
t.plan(2)
|
|
26
|
+
const context = {}
|
|
27
|
+
validation[func](context)
|
|
28
|
+
t.assert.strictEqual(typeof context[symbols.bodySchema], 'undefined')
|
|
29
|
+
t.assert.strictEqual(typeof context[symbols.responseSchema], 'undefined')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test(`${func} schema - missing output schema`, t => {
|
|
33
|
+
t.plan(1)
|
|
34
|
+
const context = { schema: {} }
|
|
35
|
+
validation[func](context, null)
|
|
36
|
+
t.assert.strictEqual(typeof context[symbols.responseSchema], 'undefined')
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('build schema - output schema', t => {
|
|
41
|
+
t.plan(2)
|
|
42
|
+
const opts = {
|
|
43
|
+
schema: {
|
|
44
|
+
response: {
|
|
45
|
+
'2xx': {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
hello: { type: 'string' }
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
201: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
hello: { type: 'number' }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
validation.compileSchemasForSerialization(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
61
|
+
t.assert.strictEqual(typeof opts[symbols.responseSchema]['2xx'], 'function')
|
|
62
|
+
t.assert.strictEqual(typeof opts[symbols.responseSchema]['201'], 'function')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('build schema - body schema', t => {
|
|
66
|
+
t.plan(1)
|
|
67
|
+
const opts = {
|
|
68
|
+
schema: {
|
|
69
|
+
body: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
hello: { type: 'string' }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
78
|
+
t.assert.strictEqual(typeof opts[symbols.bodySchema], 'function')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('build schema - body with multiple content type schemas', t => {
|
|
82
|
+
t.plan(2)
|
|
83
|
+
const opts = {
|
|
84
|
+
schema: {
|
|
85
|
+
body: {
|
|
86
|
+
content: {
|
|
87
|
+
'application/json': {
|
|
88
|
+
schema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
hello: { type: 'string' }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
'text/plain': {
|
|
96
|
+
schema: { type: 'string' }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
103
|
+
t.assert.ok(opts[symbols.bodySchema]['application/json'], 'function')
|
|
104
|
+
t.assert.ok(opts[symbols.bodySchema]['text/plain'], 'function')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('build schema - avoid repeated normalize schema', t => {
|
|
108
|
+
t.plan(3)
|
|
109
|
+
const serverConfig = {}
|
|
110
|
+
const opts = {
|
|
111
|
+
schema: {
|
|
112
|
+
query: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
hello: { type: 'string' }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
121
|
+
t.assert.notStrictEqual(kSchemaVisited, undefined)
|
|
122
|
+
t.assert.strictEqual(opts.schema[kSchemaVisited], true)
|
|
123
|
+
t.assert.strictEqual(opts.schema, normalizeSchema(opts.schema, serverConfig))
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('build schema - query schema', t => {
|
|
127
|
+
t.plan(2)
|
|
128
|
+
const serverConfig = {}
|
|
129
|
+
const opts = {
|
|
130
|
+
schema: {
|
|
131
|
+
query: {
|
|
132
|
+
type: 'object',
|
|
133
|
+
properties: {
|
|
134
|
+
hello: { type: 'string' }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
140
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
141
|
+
t.assert.ok(typeof opts[symbols.querystringSchema].schema.type === 'string')
|
|
142
|
+
t.assert.strictEqual(typeof opts[symbols.querystringSchema], 'function')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('build schema - query schema abbreviated', t => {
|
|
146
|
+
t.plan(2)
|
|
147
|
+
const serverConfig = {}
|
|
148
|
+
const opts = {
|
|
149
|
+
schema: {
|
|
150
|
+
query: {
|
|
151
|
+
type: 'object',
|
|
152
|
+
properties: {
|
|
153
|
+
hello: { type: 'string' }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
159
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
160
|
+
t.assert.ok(typeof opts[symbols.querystringSchema].schema.type === 'string')
|
|
161
|
+
t.assert.strictEqual(typeof opts[symbols.querystringSchema], 'function')
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('build schema - querystring schema', t => {
|
|
165
|
+
t.plan(2)
|
|
166
|
+
const opts = {
|
|
167
|
+
schema: {
|
|
168
|
+
querystring: {
|
|
169
|
+
type: 'object',
|
|
170
|
+
properties: {
|
|
171
|
+
hello: { type: 'string' }
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
177
|
+
t.assert.ok(typeof opts[symbols.querystringSchema].schema.type === 'string')
|
|
178
|
+
t.assert.strictEqual(typeof opts[symbols.querystringSchema], 'function')
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('build schema - querystring schema abbreviated', t => {
|
|
182
|
+
t.plan(2)
|
|
183
|
+
const serverConfig = {}
|
|
184
|
+
const opts = {
|
|
185
|
+
schema: {
|
|
186
|
+
querystring: {
|
|
187
|
+
type: 'object',
|
|
188
|
+
properties: {
|
|
189
|
+
hello: { type: 'string' }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
195
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
196
|
+
t.assert.ok(typeof opts[symbols.querystringSchema].schema.type === 'string')
|
|
197
|
+
t.assert.strictEqual(typeof opts[symbols.querystringSchema], 'function')
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
test('build schema - must throw if querystring and query schema exist', t => {
|
|
201
|
+
t.plan(2)
|
|
202
|
+
try {
|
|
203
|
+
const serverConfig = {}
|
|
204
|
+
const opts = {
|
|
205
|
+
schema: {
|
|
206
|
+
query: {
|
|
207
|
+
type: 'object',
|
|
208
|
+
properties: {
|
|
209
|
+
hello: { type: 'string' }
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
querystring: {
|
|
213
|
+
type: 'object',
|
|
214
|
+
properties: {
|
|
215
|
+
hello: { type: 'string' }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
221
|
+
} catch (err) {
|
|
222
|
+
t.assert.strictEqual(err.code, 'FST_ERR_SCH_DUPLICATE')
|
|
223
|
+
t.assert.strictEqual(err.message, 'Schema with \'querystring\' already present!')
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
test('build schema - params schema', t => {
|
|
228
|
+
t.plan(1)
|
|
229
|
+
const opts = {
|
|
230
|
+
schema: {
|
|
231
|
+
params: {
|
|
232
|
+
type: 'object',
|
|
233
|
+
properties: {
|
|
234
|
+
hello: { type: 'string' }
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
240
|
+
t.assert.strictEqual(typeof opts[symbols.paramsSchema], 'function')
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
test('build schema - headers schema', t => {
|
|
244
|
+
t.plan(1)
|
|
245
|
+
const opts = {
|
|
246
|
+
schema: {
|
|
247
|
+
headers: {
|
|
248
|
+
type: 'object',
|
|
249
|
+
properties: {
|
|
250
|
+
'content-type': { type: 'string' }
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
256
|
+
t.assert.strictEqual(typeof opts[symbols.headersSchema], 'function')
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
test('build schema - headers are lowercase', t => {
|
|
260
|
+
t.plan(1)
|
|
261
|
+
const opts = {
|
|
262
|
+
schema: {
|
|
263
|
+
headers: {
|
|
264
|
+
type: 'object',
|
|
265
|
+
properties: {
|
|
266
|
+
'Content-Type': { type: 'string' }
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
|
|
272
|
+
t.assert.ok(schema.properties['content-type'], 'lowercase content-type exists')
|
|
273
|
+
return () => { }
|
|
274
|
+
})
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
test('build schema - headers are not lowercased in case of custom object', t => {
|
|
278
|
+
t.plan(1)
|
|
279
|
+
|
|
280
|
+
class Headers { }
|
|
281
|
+
const opts = {
|
|
282
|
+
schema: {
|
|
283
|
+
headers: new Headers()
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
|
|
287
|
+
t.assert.ok(schema, Headers)
|
|
288
|
+
return () => { }
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
test('build schema - headers are not lowercased in case of custom validator provided', t => {
|
|
293
|
+
t.plan(1)
|
|
294
|
+
|
|
295
|
+
class Headers { }
|
|
296
|
+
const opts = {
|
|
297
|
+
schema: {
|
|
298
|
+
headers: new Headers()
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
|
|
302
|
+
t.assert.ok(schema, Headers)
|
|
303
|
+
return () => { }
|
|
304
|
+
}, true)
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
test('build schema - uppercased headers are not included', t => {
|
|
308
|
+
t.plan(1)
|
|
309
|
+
const opts = {
|
|
310
|
+
schema: {
|
|
311
|
+
headers: {
|
|
312
|
+
type: 'object',
|
|
313
|
+
properties: {
|
|
314
|
+
'Content-Type': { type: 'string' }
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
|
|
320
|
+
t.assert.ok(!('Content-Type' in schema.properties), 'uppercase does not exist')
|
|
321
|
+
return () => { }
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
test('build schema - mixed schema types are individually skipped or normalized', t => {
|
|
326
|
+
t.plan(2)
|
|
327
|
+
|
|
328
|
+
class CustomSchemaClass { }
|
|
329
|
+
|
|
330
|
+
const testCases = [{
|
|
331
|
+
schema: {
|
|
332
|
+
body: new CustomSchemaClass()
|
|
333
|
+
},
|
|
334
|
+
assertions: (schema) => {
|
|
335
|
+
t.assert.ok(schema.body, CustomSchemaClass)
|
|
336
|
+
}
|
|
337
|
+
}, {
|
|
338
|
+
schema: {
|
|
339
|
+
response: {
|
|
340
|
+
200: new CustomSchemaClass()
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
assertions: (schema) => {
|
|
344
|
+
t.assert.ok(schema.response[200], CustomSchemaClass)
|
|
345
|
+
}
|
|
346
|
+
}]
|
|
347
|
+
|
|
348
|
+
testCases.forEach((testCase) => {
|
|
349
|
+
const result = normalizeSchema(testCase.schema, {})
|
|
350
|
+
testCase.assertions(result)
|
|
351
|
+
})
|
|
352
|
+
})
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
const http = require('node:http')
|
|
5
|
+
const Fastify = require('../fastify')
|
|
6
|
+
const { setTimeout } = require('node:timers')
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Ensure that a socket error during the request does not cause the
|
|
10
|
+
* onSend hook to be called multiple times.
|
|
11
|
+
*
|
|
12
|
+
* @see https://github.com/fastify/fastify/issues/4959
|
|
13
|
+
*/
|
|
14
|
+
function runBadClientCall (reqOptions, payload, waitBeforeDestroy) {
|
|
15
|
+
let innerResolve, innerReject
|
|
16
|
+
const promise = new Promise((resolve, reject) => {
|
|
17
|
+
innerResolve = resolve
|
|
18
|
+
innerReject = reject
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const postData = JSON.stringify(payload)
|
|
22
|
+
|
|
23
|
+
const req = http.request({
|
|
24
|
+
...reqOptions,
|
|
25
|
+
headers: {
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
'Content-Length': Buffer.byteLength(postData)
|
|
28
|
+
}
|
|
29
|
+
}, () => {
|
|
30
|
+
innerReject(new Error('Request should have failed'))
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Kill the socket after the request has been fully written.
|
|
34
|
+
// Destroying it on `connect` can race before any bytes are sent, making the
|
|
35
|
+
// server-side assertions (hooks/handler) non-deterministic.
|
|
36
|
+
//
|
|
37
|
+
// To keep the test deterministic, we optionally wait for a server-side signal
|
|
38
|
+
// (e.g. onSend entered) before aborting the client.
|
|
39
|
+
let socket
|
|
40
|
+
req.on('socket', (s) => { socket = s })
|
|
41
|
+
req.on('finish', () => {
|
|
42
|
+
if (waitBeforeDestroy && typeof waitBeforeDestroy.then === 'function') {
|
|
43
|
+
Promise.race([
|
|
44
|
+
waitBeforeDestroy,
|
|
45
|
+
new Promise(resolve => setTimeout(resolve, 200))
|
|
46
|
+
]).then(() => {
|
|
47
|
+
if (socket) socket.destroy()
|
|
48
|
+
}, innerResolve)
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
setTimeout(() => { socket.destroy() }, 0)
|
|
52
|
+
})
|
|
53
|
+
req.on('error', innerResolve)
|
|
54
|
+
req.write(postData)
|
|
55
|
+
req.end()
|
|
56
|
+
|
|
57
|
+
return promise
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
test('should handle a socket error', async (t) => {
|
|
61
|
+
t.plan(4)
|
|
62
|
+
const fastify = Fastify()
|
|
63
|
+
|
|
64
|
+
let resolveOnSendEntered
|
|
65
|
+
const onSendEntered = new Promise((resolve) => {
|
|
66
|
+
resolveOnSendEntered = resolve
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
function shouldNotHappen () {
|
|
70
|
+
t.assert.fail('This should not happen')
|
|
71
|
+
}
|
|
72
|
+
process.on('unhandledRejection', shouldNotHappen)
|
|
73
|
+
|
|
74
|
+
t.after(() => {
|
|
75
|
+
fastify.close()
|
|
76
|
+
process.removeListener('unhandledRejection', shouldNotHappen)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
fastify.addHook('onRequest', async (request, reply) => {
|
|
80
|
+
t.assert.ok('onRequest hook called')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
fastify.addHook('onSend', async (request, reply, payload) => {
|
|
84
|
+
if (request.onSendCalled) {
|
|
85
|
+
t.assert.fail('onSend hook called more than once')
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
t.assert.ok('onSend hook called')
|
|
90
|
+
request.onSendCalled = true
|
|
91
|
+
|
|
92
|
+
if (resolveOnSendEntered) {
|
|
93
|
+
resolveOnSendEntered()
|
|
94
|
+
resolveOnSendEntered = null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Introduce a delay (gives time for client-side abort to happen while the
|
|
98
|
+
// request has already been processed, exercising the original issue).
|
|
99
|
+
await new Promise(resolve => setTimeout(resolve, 50))
|
|
100
|
+
return payload
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// The handler must be async to trigger the error
|
|
104
|
+
fastify.put('/', async (request, reply) => {
|
|
105
|
+
t.assert.ok('PUT handler called')
|
|
106
|
+
return reply.send({ hello: 'world' })
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
await fastify.listen({ port: 0 })
|
|
110
|
+
|
|
111
|
+
const err = await runBadClientCall({
|
|
112
|
+
hostname: 'localhost',
|
|
113
|
+
port: fastify.server.address().port,
|
|
114
|
+
path: '/',
|
|
115
|
+
method: 'PUT'
|
|
116
|
+
}, { test: 'me' }, onSendEntered)
|
|
117
|
+
t.assert.equal(err.code, 'ECONNRESET')
|
|
118
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Fastify = require('..')
|
|
4
|
+
const http = require('node:http')
|
|
5
|
+
const { test } = require('node:test')
|
|
6
|
+
|
|
7
|
+
test('keepAliveTimeout', t => {
|
|
8
|
+
t.plan(6)
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
Fastify({ keepAliveTimeout: 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({ keepAliveTimeout: [] })
|
|
19
|
+
t.assert.fail('option must be an integer')
|
|
20
|
+
} catch (err) {
|
|
21
|
+
t.assert.ok(err)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const httpServer = Fastify({ keepAliveTimeout: 1 }).server
|
|
25
|
+
t.assert.strictEqual(httpServer.keepAliveTimeout, 1)
|
|
26
|
+
|
|
27
|
+
const httpsServer = Fastify({ keepAliveTimeout: 2, https: {} }).server
|
|
28
|
+
t.assert.strictEqual(httpsServer.keepAliveTimeout, 2)
|
|
29
|
+
|
|
30
|
+
const http2Server = Fastify({ keepAliveTimeout: 3, http2: true }).server
|
|
31
|
+
t.assert.notStrictEqual(http2Server.keepAliveTimeout, 3)
|
|
32
|
+
|
|
33
|
+
const serverFactory = (handler, _) => {
|
|
34
|
+
const server = http.createServer((req, res) => {
|
|
35
|
+
handler(req, res)
|
|
36
|
+
})
|
|
37
|
+
server.keepAliveTimeout = 5
|
|
38
|
+
return server
|
|
39
|
+
}
|
|
40
|
+
const customServer = Fastify({ keepAliveTimeout: 4, serverFactory }).server
|
|
41
|
+
t.assert.strictEqual(customServer.keepAliveTimeout, 5)
|
|
42
|
+
})
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { networkInterfaces } = require('node:os')
|
|
4
|
+
const { test, before } = require('node:test')
|
|
5
|
+
const Fastify = require('..')
|
|
6
|
+
const helper = require('./helper')
|
|
7
|
+
|
|
8
|
+
let localhost
|
|
9
|
+
let localhostForURL
|
|
10
|
+
|
|
11
|
+
before(async function () {
|
|
12
|
+
[localhost, localhostForURL] = await helper.getLoopbackHost()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('listen works without arguments', async t => {
|
|
16
|
+
const doNotWarn = () => {
|
|
17
|
+
t.assert.fail('should not be deprecated')
|
|
18
|
+
}
|
|
19
|
+
process.on('warning', doNotWarn)
|
|
20
|
+
|
|
21
|
+
const fastify = Fastify()
|
|
22
|
+
t.after(() => {
|
|
23
|
+
fastify.close()
|
|
24
|
+
process.removeListener('warning', doNotWarn)
|
|
25
|
+
})
|
|
26
|
+
await fastify.listen()
|
|
27
|
+
const address = fastify.server.address()
|
|
28
|
+
t.assert.strictEqual(address.address, localhost)
|
|
29
|
+
t.assert.ok(address.port > 0)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('Async/await listen with arguments', async t => {
|
|
33
|
+
const doNotWarn = () => {
|
|
34
|
+
t.assert.fail('should not be deprecated')
|
|
35
|
+
}
|
|
36
|
+
process.on('warning', doNotWarn)
|
|
37
|
+
|
|
38
|
+
const fastify = Fastify()
|
|
39
|
+
t.after(() => {
|
|
40
|
+
fastify.close()
|
|
41
|
+
process.removeListener('warning', doNotWarn)
|
|
42
|
+
})
|
|
43
|
+
const addr = await fastify.listen({ port: 0, host: '0.0.0.0' })
|
|
44
|
+
const address = fastify.server.address()
|
|
45
|
+
const { protocol, hostname, port, pathname } = new URL(addr)
|
|
46
|
+
t.assert.strictEqual(protocol, 'http:')
|
|
47
|
+
t.assert.ok(Object.values(networkInterfaces())
|
|
48
|
+
.flat()
|
|
49
|
+
.filter(({ internal }) => internal)
|
|
50
|
+
.some(({ address }) => address === hostname))
|
|
51
|
+
t.assert.strictEqual(pathname, '/')
|
|
52
|
+
t.assert.strictEqual(Number(port), address.port)
|
|
53
|
+
t.assert.deepEqual(address, {
|
|
54
|
+
address: '0.0.0.0',
|
|
55
|
+
family: 'IPv4',
|
|
56
|
+
port: address.port
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('listen accepts a callback', (t, done) => {
|
|
61
|
+
t.plan(2)
|
|
62
|
+
const doNotWarn = () => {
|
|
63
|
+
t.assert.fail('should not be deprecated')
|
|
64
|
+
}
|
|
65
|
+
process.on('warning', doNotWarn)
|
|
66
|
+
|
|
67
|
+
const fastify = Fastify()
|
|
68
|
+
t.after(() => {
|
|
69
|
+
fastify.close()
|
|
70
|
+
process.removeListener('warning', doNotWarn)
|
|
71
|
+
})
|
|
72
|
+
fastify.listen({ port: 0 }, (err) => {
|
|
73
|
+
t.assert.ifError(err)
|
|
74
|
+
t.assert.strictEqual(fastify.server.address().address, localhost)
|
|
75
|
+
done()
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('listen accepts options and a callback', (t, done) => {
|
|
80
|
+
t.plan(1)
|
|
81
|
+
const doNotWarn = () => {
|
|
82
|
+
t.assert.fail('should not be deprecated')
|
|
83
|
+
}
|
|
84
|
+
process.on('warning', doNotWarn)
|
|
85
|
+
|
|
86
|
+
const fastify = Fastify()
|
|
87
|
+
t.after(() => {
|
|
88
|
+
fastify.close()
|
|
89
|
+
process.removeListener('warning', doNotWarn)
|
|
90
|
+
})
|
|
91
|
+
fastify.listen({
|
|
92
|
+
port: 0,
|
|
93
|
+
host: 'localhost',
|
|
94
|
+
backlog: 511,
|
|
95
|
+
exclusive: false,
|
|
96
|
+
readableAll: false,
|
|
97
|
+
writableAll: false,
|
|
98
|
+
ipv6Only: false
|
|
99
|
+
}, (err) => {
|
|
100
|
+
t.assert.ifError(err)
|
|
101
|
+
done()
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('listen after Promise.resolve()', (t, done) => {
|
|
106
|
+
t.plan(2)
|
|
107
|
+
const fastify = Fastify()
|
|
108
|
+
t.after(() => fastify.close())
|
|
109
|
+
Promise.resolve()
|
|
110
|
+
.then(() => {
|
|
111
|
+
fastify.listen({ port: 0 }, (err, address) => {
|
|
112
|
+
fastify.server.unref()
|
|
113
|
+
t.assert.strictEqual(address, `http://${localhostForURL}:${fastify.server.address().port}`)
|
|
114
|
+
t.assert.ifError(err)
|
|
115
|
+
done()
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('listen works with undefined host', async t => {
|
|
121
|
+
const doNotWarn = () => {
|
|
122
|
+
t.assert.fail('should not be deprecated')
|
|
123
|
+
}
|
|
124
|
+
process.on('warning', doNotWarn)
|
|
125
|
+
|
|
126
|
+
const fastify = Fastify()
|
|
127
|
+
t.after(() => fastify.close())
|
|
128
|
+
t.after(() => {
|
|
129
|
+
fastify.close()
|
|
130
|
+
process.removeListener('warning', doNotWarn)
|
|
131
|
+
})
|
|
132
|
+
await fastify.listen({ host: undefined, port: 0 })
|
|
133
|
+
const address = fastify.server.address()
|
|
134
|
+
t.assert.strictEqual(address.address, localhost)
|
|
135
|
+
t.assert.ok(address.port > 0)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('listen works with null host', async t => {
|
|
139
|
+
const doNotWarn = () => {
|
|
140
|
+
t.fail('should not be deprecated')
|
|
141
|
+
}
|
|
142
|
+
process.on('warning', doNotWarn)
|
|
143
|
+
|
|
144
|
+
const fastify = Fastify()
|
|
145
|
+
t.after(() => fastify.close())
|
|
146
|
+
t.after(() => {
|
|
147
|
+
fastify.close()
|
|
148
|
+
process.removeListener('warning', doNotWarn)
|
|
149
|
+
})
|
|
150
|
+
await fastify.listen({ host: null, port: 0 })
|
|
151
|
+
const address = fastify.server.address()
|
|
152
|
+
t.assert.strictEqual(address.address, localhost)
|
|
153
|
+
t.assert.ok(address.port > 0)
|
|
154
|
+
})
|