fastify 5.3.3 → 5.5.0
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/.vscode/settings.json +15 -15
- package/LICENSE +1 -1
- package/README.md +2 -0
- package/SECURITY.md +158 -2
- package/build/build-validation.js +20 -1
- package/docs/Guides/Delay-Accepting-Requests.md +8 -5
- package/docs/Guides/Ecosystem.md +20 -5
- package/docs/Guides/Migration-Guide-V5.md +6 -10
- package/docs/Guides/Recommendations.md +1 -1
- package/docs/Reference/ContentTypeParser.md +1 -1
- package/docs/Reference/Errors.md +5 -3
- package/docs/Reference/Hooks.md +16 -20
- package/docs/Reference/Lifecycle.md +2 -2
- package/docs/Reference/Logging.md +3 -3
- package/docs/Reference/Middleware.md +1 -1
- package/docs/Reference/Reply.md +8 -8
- package/docs/Reference/Request.md +2 -2
- package/docs/Reference/Routes.md +7 -6
- package/docs/Reference/Server.md +341 -200
- package/docs/Reference/TypeScript.md +1 -3
- package/docs/Reference/Validation-and-Serialization.md +56 -4
- package/docs/Reference/Warnings.md +2 -1
- package/fastify.d.ts +4 -3
- package/fastify.js +47 -34
- package/lib/configValidator.js +196 -28
- package/lib/contentTypeParser.js +41 -48
- package/lib/error-handler.js +3 -3
- package/lib/errors.js +11 -0
- package/lib/handleRequest.js +13 -17
- package/lib/pluginOverride.js +3 -1
- package/lib/promise.js +23 -0
- package/lib/reply.js +24 -30
- package/lib/request.js +3 -10
- package/lib/route.js +37 -3
- package/lib/server.js +36 -35
- package/lib/symbols.js +1 -0
- package/lib/warnings.js +19 -1
- package/package.json +14 -10
- package/test/404s.test.js +226 -325
- package/test/allow-unsafe-regex.test.js +19 -48
- package/test/als.test.js +28 -40
- package/test/async-await.test.js +84 -128
- package/test/async_hooks.test.js +18 -37
- package/test/body-limit.test.js +90 -63
- package/test/buffer.test.js +22 -0
- package/test/build-certificate.js +1 -1
- package/test/case-insensitive.test.js +44 -65
- package/test/check.test.js +17 -21
- package/test/close-pipelining.test.js +24 -15
- package/test/constrained-routes.test.js +231 -0
- package/test/custom-http-server.test.js +7 -15
- package/test/custom-parser-async.test.js +17 -22
- package/test/custom-parser.0.test.js +267 -348
- package/test/custom-parser.1.test.js +141 -191
- package/test/custom-parser.2.test.js +34 -44
- package/test/custom-parser.3.test.js +56 -104
- package/test/custom-parser.4.test.js +106 -144
- package/test/custom-parser.5.test.js +56 -75
- package/test/custom-querystring-parser.test.js +51 -77
- package/test/decorator-namespace.test._js_ +3 -4
- package/test/decorator.test.js +76 -259
- package/test/delete.test.js +101 -110
- package/test/diagnostics-channel/404.test.js +7 -15
- package/test/diagnostics-channel/async-delay-request.test.js +7 -16
- package/test/diagnostics-channel/async-request.test.js +8 -16
- package/test/diagnostics-channel/error-request.test.js +7 -15
- package/test/diagnostics-channel/sync-delay-request.test.js +7 -16
- package/test/diagnostics-channel/sync-request-reply.test.js +9 -16
- package/test/diagnostics-channel/sync-request.test.js +9 -16
- package/test/fastify-instance.test.js +1 -1
- package/test/header-overflow.test.js +18 -29
- package/test/helper.js +139 -135
- package/test/hooks-async.test.js +259 -235
- package/test/hooks.test.js +951 -996
- package/test/http-methods/copy.test.js +14 -19
- package/test/http-methods/get.test.js +131 -143
- package/test/http-methods/head.test.js +53 -84
- package/test/http-methods/lock.test.js +31 -31
- package/test/http-methods/mkcalendar.test.js +45 -72
- package/test/http-methods/mkcol.test.js +5 -9
- package/test/http-methods/move.test.js +6 -10
- package/test/http-methods/propfind.test.js +34 -44
- package/test/http-methods/proppatch.test.js +23 -29
- package/test/http-methods/report.test.js +44 -69
- package/test/http-methods/search.test.js +67 -82
- package/test/http-methods/unlock.test.js +5 -9
- package/test/http2/closing.test.js +38 -20
- package/test/http2/secure-with-fallback.test.js +31 -28
- package/test/https/custom-https-server.test.js +9 -13
- package/test/https/https.test.js +56 -53
- package/test/input-validation.js +139 -150
- package/test/internals/errors.test.js +50 -1
- package/test/internals/handle-request.test.js +72 -65
- package/test/internals/promise.test.js +63 -0
- package/test/internals/reply.test.js +277 -496
- package/test/issue-4959.test.js +12 -3
- package/test/listen.4.test.js +31 -43
- package/test/nullable-validation.test.js +33 -46
- package/test/output-validation.test.js +24 -26
- package/test/plugin.1.test.js +40 -68
- package/test/plugin.2.test.js +108 -120
- package/test/plugin.3.test.js +50 -72
- package/test/plugin.4.test.js +124 -119
- package/test/promises.test.js +42 -63
- package/test/proto-poisoning.test.js +78 -97
- package/test/register.test.js +8 -18
- package/test/request-error.test.js +57 -146
- package/test/request-id.test.js +30 -49
- package/test/route-hooks.test.js +117 -101
- package/test/route-prefix.test.js +194 -133
- package/test/route-shorthand.test.js +9 -27
- package/test/route.1.test.js +74 -131
- package/test/route.8.test.js +9 -17
- package/test/router-options.test.js +450 -0
- package/test/schema-serialization.test.js +177 -154
- package/test/schema-special-usage.test.js +165 -132
- package/test/schema-validation.test.js +254 -218
- package/test/server.test.js +143 -5
- package/test/set-error-handler.test.js +58 -1
- package/test/skip-reply-send.test.js +64 -69
- package/test/stream.1.test.js +33 -50
- package/test/stream.4.test.js +18 -28
- package/test/stream.5.test.js +11 -19
- package/test/trust-proxy.test.js +32 -58
- package/test/types/errors.test-d.ts +13 -1
- package/test/types/fastify.test-d.ts +3 -0
- package/test/types/request.test-d.ts +1 -0
- package/test/types/type-provider.test-d.ts +55 -0
- package/test/url-rewriting.test.js +45 -62
- package/test/use-semicolon-delimiter.test.js +117 -59
- package/test/versioned-routes.test.js +39 -56
- package/types/errors.d.ts +11 -1
- package/types/hooks.d.ts +1 -1
- package/types/instance.d.ts +1 -1
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +1 -0
- package/.taprc +0 -7
package/test/body-limit.test.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const Fastify = require('../fastify')
|
|
4
|
-
const sget = require('simple-get').concat
|
|
5
4
|
const zlib = require('node:zlib')
|
|
6
5
|
const { test } = require('node:test')
|
|
7
6
|
|
|
8
|
-
test('bodyLimit',
|
|
9
|
-
t.plan(
|
|
7
|
+
test('bodyLimit', async t => {
|
|
8
|
+
t.plan(4)
|
|
10
9
|
|
|
11
10
|
try {
|
|
12
11
|
Fastify({ bodyLimit: 1.3 })
|
|
@@ -28,22 +27,17 @@ test('bodyLimit', (t, done) => {
|
|
|
28
27
|
reply.send({ error: 'handler should not be called' })
|
|
29
28
|
})
|
|
30
29
|
|
|
31
|
-
fastify.listen({ port: 0 }
|
|
32
|
-
|
|
33
|
-
t.after(() => { fastify.close() })
|
|
30
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
31
|
+
t.after(() => { fastify.close() })
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
body: [],
|
|
40
|
-
json: true
|
|
41
|
-
}, (err, response, body) => {
|
|
42
|
-
t.assert.ifError(err)
|
|
43
|
-
t.assert.strictEqual(response.statusCode, 413)
|
|
44
|
-
done()
|
|
45
|
-
})
|
|
33
|
+
const result = await fetch(fastifyServer, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
body: JSON.stringify([])
|
|
46
37
|
})
|
|
38
|
+
|
|
39
|
+
t.assert.ok(!result.ok)
|
|
40
|
+
t.assert.strictEqual(result.status, 413)
|
|
47
41
|
})
|
|
48
42
|
|
|
49
43
|
test('bodyLimit is applied to decoded content', async (t) => {
|
|
@@ -114,8 +108,8 @@ test('bodyLimit is applied to decoded content', async (t) => {
|
|
|
114
108
|
})
|
|
115
109
|
})
|
|
116
110
|
|
|
117
|
-
test('default request.routeOptions.bodyLimit should be 1048576',
|
|
118
|
-
t.plan(
|
|
111
|
+
test('default request.routeOptions.bodyLimit should be 1048576', async t => {
|
|
112
|
+
t.plan(3)
|
|
119
113
|
const fastify = Fastify()
|
|
120
114
|
fastify.post('/default-bodylimit', {
|
|
121
115
|
handler (request, reply) {
|
|
@@ -123,26 +117,20 @@ test('default request.routeOptions.bodyLimit should be 1048576', (t, done) => {
|
|
|
123
117
|
reply.send({ })
|
|
124
118
|
}
|
|
125
119
|
})
|
|
126
|
-
fastify.listen({ port: 0 }
|
|
127
|
-
|
|
128
|
-
t.after(() => { fastify.close() })
|
|
120
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
121
|
+
t.after(() => { fastify.close() })
|
|
129
122
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
body: [],
|
|
135
|
-
json: true
|
|
136
|
-
}, (err, response, body) => {
|
|
137
|
-
t.assert.ifError(err)
|
|
138
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
139
|
-
done()
|
|
140
|
-
})
|
|
123
|
+
const result = await fetch(fastifyServer + '/default-bodylimit', {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
headers: { 'Content-Type': 'application/json' },
|
|
126
|
+
body: JSON.stringify([])
|
|
141
127
|
})
|
|
128
|
+
t.assert.ok(result.ok)
|
|
129
|
+
t.assert.strictEqual(result.status, 200)
|
|
142
130
|
})
|
|
143
131
|
|
|
144
|
-
test('request.routeOptions.bodyLimit should be equal to route limit',
|
|
145
|
-
t.plan(
|
|
132
|
+
test('request.routeOptions.bodyLimit should be equal to route limit', async t => {
|
|
133
|
+
t.plan(3)
|
|
146
134
|
const fastify = Fastify({ bodyLimit: 1 })
|
|
147
135
|
fastify.post('/route-limit', {
|
|
148
136
|
bodyLimit: 1000,
|
|
@@ -151,26 +139,20 @@ test('request.routeOptions.bodyLimit should be equal to route limit', (t, done)
|
|
|
151
139
|
reply.send({})
|
|
152
140
|
}
|
|
153
141
|
})
|
|
154
|
-
fastify.listen({ port: 0 }
|
|
155
|
-
|
|
156
|
-
t.after(() => { fastify.close() })
|
|
142
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
143
|
+
t.after(() => { fastify.close() })
|
|
157
144
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
body: [],
|
|
163
|
-
json: true
|
|
164
|
-
}, (err, response, body) => {
|
|
165
|
-
t.assert.ifError(err)
|
|
166
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
167
|
-
done()
|
|
168
|
-
})
|
|
145
|
+
const result = await fetch(fastifyServer + '/route-limit', {
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: { 'Content-Type': 'application/json' },
|
|
148
|
+
body: JSON.stringify([])
|
|
169
149
|
})
|
|
150
|
+
t.assert.ok(result.ok)
|
|
151
|
+
t.assert.strictEqual(result.status, 200)
|
|
170
152
|
})
|
|
171
153
|
|
|
172
|
-
test('request.routeOptions.bodyLimit should be equal to server limit',
|
|
173
|
-
t.plan(
|
|
154
|
+
test('request.routeOptions.bodyLimit should be equal to server limit', async t => {
|
|
155
|
+
t.plan(3)
|
|
174
156
|
const fastify = Fastify({ bodyLimit: 100 })
|
|
175
157
|
fastify.post('/server-limit', {
|
|
176
158
|
handler (request, reply) {
|
|
@@ -178,20 +160,65 @@ test('request.routeOptions.bodyLimit should be equal to server limit', (t, done)
|
|
|
178
160
|
reply.send({})
|
|
179
161
|
}
|
|
180
162
|
})
|
|
181
|
-
fastify.listen({ port: 0 }
|
|
182
|
-
|
|
183
|
-
|
|
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
|
+
})
|
|
184
174
|
|
|
185
|
-
|
|
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({
|
|
186
201
|
method: 'POST',
|
|
187
|
-
url: '
|
|
188
|
-
headers: { 'Content-Type': '
|
|
189
|
-
|
|
190
|
-
json: true
|
|
191
|
-
}, (err, response, body) => {
|
|
192
|
-
t.assert.ifError(err)
|
|
193
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
194
|
-
done()
|
|
202
|
+
url: '/test-utf8',
|
|
203
|
+
headers: { 'Content-Type': 'text/plain', 'Content-Length': null },
|
|
204
|
+
payload: multiByteString
|
|
195
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
|
|
196
223
|
})
|
|
197
224
|
})
|
package/test/buffer.test.js
CHANGED
|
@@ -49,4 +49,26 @@ test('Buffer test', async t => {
|
|
|
49
49
|
statusCode: 400
|
|
50
50
|
})
|
|
51
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
|
+
})
|
|
52
74
|
})
|
|
@@ -91,7 +91,7 @@ function selfCert (opts) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
function buildCertificate () {
|
|
95
95
|
// "global" is used in here because "t.context" is only supported by "t.beforeEach" and "t.afterEach"
|
|
96
96
|
// For the test case which execute this code which will be using `t.before` and it can reduce the
|
|
97
97
|
// number of times executing it.
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('node:test')
|
|
4
4
|
const Fastify = require('..')
|
|
5
|
-
const sget = require('simple-get').concat
|
|
6
5
|
|
|
7
|
-
test('case insensitive', (t
|
|
8
|
-
t.plan(
|
|
6
|
+
test('case insensitive', async (t) => {
|
|
7
|
+
t.plan(3)
|
|
9
8
|
|
|
10
9
|
const fastify = Fastify({
|
|
11
10
|
caseSensitive: false
|
|
@@ -16,25 +15,19 @@ test('case insensitive', (t, done) => {
|
|
|
16
15
|
reply.send({ hello: 'world' })
|
|
17
16
|
})
|
|
18
17
|
|
|
19
|
-
fastify.listen({ port: 0 }
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
28
|
-
t.assert.deepStrictEqual(JSON.parse(body), {
|
|
29
|
-
hello: 'world'
|
|
30
|
-
})
|
|
31
|
-
done()
|
|
32
|
-
})
|
|
18
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
19
|
+
|
|
20
|
+
const result = await fetch(`${fastifyServer}/FOO`)
|
|
21
|
+
|
|
22
|
+
t.assert.ok(result.ok)
|
|
23
|
+
t.assert.strictEqual(result.status, 200)
|
|
24
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
25
|
+
hello: 'world'
|
|
33
26
|
})
|
|
34
27
|
})
|
|
35
28
|
|
|
36
|
-
test('case insensitive inject',
|
|
37
|
-
t.plan(
|
|
29
|
+
test('case insensitive inject', async t => {
|
|
30
|
+
t.plan(2)
|
|
38
31
|
|
|
39
32
|
const fastify = Fastify({
|
|
40
33
|
caseSensitive: false
|
|
@@ -45,25 +38,21 @@ test('case insensitive inject', (t, done) => {
|
|
|
45
38
|
reply.send({ hello: 'world' })
|
|
46
39
|
})
|
|
47
40
|
|
|
48
|
-
fastify.listen({ port: 0 }
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
hello: 'world'
|
|
59
|
-
})
|
|
60
|
-
done()
|
|
61
|
-
})
|
|
41
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
42
|
+
|
|
43
|
+
const result = await fastify.inject({
|
|
44
|
+
method: 'GET',
|
|
45
|
+
url: fastifyServer + '/FOO'
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
t.assert.strictEqual(result.statusCode, 200)
|
|
49
|
+
t.assert.deepStrictEqual(result.json(), {
|
|
50
|
+
hello: 'world'
|
|
62
51
|
})
|
|
63
52
|
})
|
|
64
53
|
|
|
65
|
-
test('case insensitive (parametric)', (t
|
|
66
|
-
t.plan(
|
|
54
|
+
test('case insensitive (parametric)', async (t) => {
|
|
55
|
+
t.plan(4)
|
|
67
56
|
|
|
68
57
|
const fastify = Fastify({
|
|
69
58
|
caseSensitive: false
|
|
@@ -75,25 +64,21 @@ test('case insensitive (parametric)', (t, done) => {
|
|
|
75
64
|
reply.send({ hello: 'world' })
|
|
76
65
|
})
|
|
77
66
|
|
|
78
|
-
fastify.listen({ port: 0 }
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
hello: 'world'
|
|
89
|
-
})
|
|
90
|
-
done()
|
|
91
|
-
})
|
|
67
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
68
|
+
|
|
69
|
+
const result = await fetch(`${fastifyServer}/FoO/bAr`, {
|
|
70
|
+
method: 'GET'
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
t.assert.ok(result.ok)
|
|
74
|
+
t.assert.strictEqual(result.status, 200)
|
|
75
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
76
|
+
hello: 'world'
|
|
92
77
|
})
|
|
93
78
|
})
|
|
94
79
|
|
|
95
|
-
test('case insensitive (wildcard)', (t
|
|
96
|
-
t.plan(
|
|
80
|
+
test('case insensitive (wildcard)', async (t) => {
|
|
81
|
+
t.plan(4)
|
|
97
82
|
|
|
98
83
|
const fastify = Fastify({
|
|
99
84
|
caseSensitive: false
|
|
@@ -105,19 +90,13 @@ test('case insensitive (wildcard)', (t, done) => {
|
|
|
105
90
|
reply.send({ hello: 'world' })
|
|
106
91
|
})
|
|
107
92
|
|
|
108
|
-
fastify.listen({ port: 0 }
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
117
|
-
t.assert.deepStrictEqual(JSON.parse(body), {
|
|
118
|
-
hello: 'world'
|
|
119
|
-
})
|
|
120
|
-
done()
|
|
121
|
-
})
|
|
93
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
94
|
+
|
|
95
|
+
const result = await fetch(`${fastifyServer}/FoO/bAr/baZ`)
|
|
96
|
+
|
|
97
|
+
t.assert.ok(result.ok)
|
|
98
|
+
t.assert.strictEqual(result.status, 200)
|
|
99
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
100
|
+
hello: 'world'
|
|
122
101
|
})
|
|
123
102
|
})
|
package/test/check.test.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { test } = require('node:test')
|
|
4
4
|
const { S } = require('fluent-json-schema')
|
|
5
5
|
const Fastify = require('..')
|
|
6
|
-
const sget = require('simple-get').concat
|
|
7
6
|
|
|
8
7
|
const BadRequestSchema = S.object()
|
|
9
8
|
.prop('statusCode', S.number())
|
|
@@ -105,32 +104,29 @@ const handler = (request, reply) => {
|
|
|
105
104
|
})
|
|
106
105
|
}
|
|
107
106
|
|
|
108
|
-
test('serialize the response for a Bad Request error, as defined on the schema',
|
|
107
|
+
test('serialize the response for a Bad Request error, as defined on the schema', async t => {
|
|
109
108
|
const fastify = Fastify({})
|
|
110
109
|
|
|
111
110
|
t.after(() => fastify.close())
|
|
112
111
|
|
|
113
112
|
fastify.post('/', options, handler)
|
|
114
113
|
|
|
115
|
-
fastify.listen({ port: 0 }
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
})
|
|
132
|
-
done()
|
|
133
|
-
})
|
|
114
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
115
|
+
|
|
116
|
+
const result = await fetch(fastifyServer, {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: {
|
|
119
|
+
'Content-Type': 'application/json'
|
|
120
|
+
},
|
|
121
|
+
body: '12'
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
t.assert.ok(!result.ok)
|
|
125
|
+
t.assert.strictEqual(result.status, 400)
|
|
126
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
127
|
+
statusCode: 400,
|
|
128
|
+
error: 'Bad Request',
|
|
129
|
+
message: 'body must be object'
|
|
134
130
|
})
|
|
135
131
|
})
|
|
136
132
|
|
|
@@ -11,8 +11,10 @@ test('Should return 503 while closing - pipelining', async t => {
|
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
fastify.get('/', async (req, reply) => {
|
|
14
|
+
// Simulate a delay to allow pipelining to kick in
|
|
15
|
+
await new Promise(resolve => setTimeout(resolve, 5))
|
|
16
|
+
reply.send({ hello: 'world' })
|
|
14
17
|
fastify.close()
|
|
15
|
-
return { hello: 'world' }
|
|
16
18
|
})
|
|
17
19
|
|
|
18
20
|
await fastify.listen({ port: 0 })
|
|
@@ -21,14 +23,19 @@ test('Should return 503 while closing - pipelining', async t => {
|
|
|
21
23
|
pipelining: 2
|
|
22
24
|
})
|
|
23
25
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
instance.request({ path: '/', method: 'GET' }),
|
|
27
|
-
instance.request({ path: '/', method: 'GET' })
|
|
28
|
-
instance.request({ path: '/', method: 'GET' })
|
|
26
|
+
const [firstRequest, secondRequest, thirdRequest] = await Promise.allSettled([
|
|
27
|
+
instance.request({ path: '/', method: 'GET', blocking: false }),
|
|
28
|
+
instance.request({ path: '/', method: 'GET', blocking: false }),
|
|
29
|
+
instance.request({ path: '/', method: 'GET', blocking: false })
|
|
29
30
|
])
|
|
30
|
-
|
|
31
|
-
t.assert.
|
|
31
|
+
t.assert.strictEqual(firstRequest.status, 'fulfilled')
|
|
32
|
+
t.assert.strictEqual(secondRequest.status, 'fulfilled')
|
|
33
|
+
|
|
34
|
+
t.assert.strictEqual(firstRequest.value.statusCode, 200)
|
|
35
|
+
t.assert.strictEqual(secondRequest.value.statusCode, 200)
|
|
36
|
+
|
|
37
|
+
t.assert.strictEqual(thirdRequest.status, 'fulfilled')
|
|
38
|
+
t.assert.strictEqual(thirdRequest.value.statusCode, 503)
|
|
32
39
|
|
|
33
40
|
await instance.close()
|
|
34
41
|
})
|
|
@@ -42,6 +49,8 @@ test('Should close the socket abruptly - pipelining - return503OnClosing: false'
|
|
|
42
49
|
})
|
|
43
50
|
|
|
44
51
|
fastify.get('/', async (req, reply) => {
|
|
52
|
+
// Simulate a delay to allow pipelining to kick in
|
|
53
|
+
await new Promise(resolve => setTimeout(resolve, 5))
|
|
45
54
|
reply.send({ hello: 'world' })
|
|
46
55
|
fastify.close()
|
|
47
56
|
})
|
|
@@ -49,21 +58,21 @@ test('Should close the socket abruptly - pipelining - return503OnClosing: false'
|
|
|
49
58
|
await fastify.listen({ port: 0 })
|
|
50
59
|
|
|
51
60
|
const instance = new Client('http://localhost:' + fastify.server.address().port, {
|
|
52
|
-
pipelining:
|
|
61
|
+
pipelining: 1
|
|
53
62
|
})
|
|
54
63
|
|
|
55
64
|
const responses = await Promise.allSettled([
|
|
56
|
-
instance.request({ path: '/', method: 'GET' }),
|
|
57
|
-
instance.request({ path: '/', method: 'GET' }),
|
|
58
|
-
instance.request({ path: '/', method: 'GET' }),
|
|
59
|
-
instance.request({ path: '/', method: 'GET' })
|
|
65
|
+
instance.request({ path: '/', method: 'GET', blocking: false }),
|
|
66
|
+
instance.request({ path: '/', method: 'GET', blocking: false }),
|
|
67
|
+
instance.request({ path: '/', method: 'GET', blocking: false }),
|
|
68
|
+
instance.request({ path: '/', method: 'GET', blocking: false })
|
|
60
69
|
])
|
|
61
70
|
|
|
62
71
|
const fulfilled = responses.filter(r => r.status === 'fulfilled')
|
|
63
72
|
const rejected = responses.filter(r => r.status === 'rejected')
|
|
64
73
|
|
|
65
|
-
t.assert.strictEqual(fulfilled.length,
|
|
66
|
-
t.assert.strictEqual(rejected.length,
|
|
74
|
+
t.assert.strictEqual(fulfilled.length, 1)
|
|
75
|
+
t.assert.strictEqual(rejected.length, 3)
|
|
67
76
|
|
|
68
77
|
await instance.close()
|
|
69
78
|
})
|