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
|
@@ -1,42 +1,35 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { test } = require('node:test')
|
|
4
|
-
const sget = require('simple-get').concat
|
|
5
4
|
const Fastify = require('../fastify')
|
|
6
5
|
const jsonParser = require('fast-json-body')
|
|
7
|
-
const {
|
|
6
|
+
const { plainTextParser } = require('./helper')
|
|
8
7
|
|
|
9
8
|
process.removeAllListeners('warning')
|
|
10
9
|
|
|
11
|
-
test('cannot remove all content type parsers after binding', (t
|
|
12
|
-
t.plan(
|
|
10
|
+
test('cannot remove all content type parsers after binding', async (t) => {
|
|
11
|
+
t.plan(1)
|
|
13
12
|
|
|
14
13
|
const fastify = Fastify()
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
done()
|
|
21
|
-
})
|
|
15
|
+
t.after(() => fastify.close())
|
|
16
|
+
|
|
17
|
+
await fastify.listen({ port: 0 })
|
|
18
|
+
t.assert.throws(() => fastify.removeAllContentTypeParsers())
|
|
22
19
|
})
|
|
23
20
|
|
|
24
|
-
test('cannot remove content type parsers after binding', (t
|
|
25
|
-
t.plan(
|
|
21
|
+
test('cannot remove content type parsers after binding', async (t) => {
|
|
22
|
+
t.plan(1)
|
|
26
23
|
|
|
27
24
|
const fastify = Fastify()
|
|
28
|
-
|
|
29
25
|
t.after(() => fastify.close())
|
|
30
26
|
|
|
31
|
-
fastify.listen({ port: 0 }
|
|
32
|
-
|
|
33
|
-
t.assert.throws(() => fastify.removeContentTypeParser('application/json'))
|
|
34
|
-
done()
|
|
35
|
-
})
|
|
27
|
+
await fastify.listen({ port: 0 })
|
|
28
|
+
t.assert.throws(() => fastify.removeContentTypeParser('application/json'))
|
|
36
29
|
})
|
|
37
30
|
|
|
38
|
-
test('should be able to override the default json parser after removeAllContentTypeParsers', (t
|
|
39
|
-
t.plan(
|
|
31
|
+
test('should be able to override the default json parser after removeAllContentTypeParsers', async (t) => {
|
|
32
|
+
t.plan(4)
|
|
40
33
|
|
|
41
34
|
const fastify = Fastify()
|
|
42
35
|
|
|
@@ -53,28 +46,24 @@ test('should be able to override the default json parser after removeAllContentT
|
|
|
53
46
|
})
|
|
54
47
|
})
|
|
55
48
|
|
|
56
|
-
fastify.listen({ port: 0 }
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
'Content-Type': 'application/json'
|
|
65
|
-
}
|
|
66
|
-
}, (err, response, body) => {
|
|
67
|
-
t.assert.ifError(err)
|
|
68
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
69
|
-
t.assert.deepStrictEqual(body.toString(), JSON.stringify({ hello: 'world' }))
|
|
70
|
-
fastify.close()
|
|
71
|
-
done()
|
|
72
|
-
})
|
|
49
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
50
|
+
|
|
51
|
+
const result = await fetch(fastifyServer, {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
body: JSON.stringify({ hello: 'world' }),
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json'
|
|
56
|
+
}
|
|
73
57
|
})
|
|
58
|
+
|
|
59
|
+
t.assert.ok(result.ok)
|
|
60
|
+
t.assert.strictEqual(result.status, 200)
|
|
61
|
+
t.assert.deepStrictEqual(await result.text(), JSON.stringify({ hello: 'world' }))
|
|
62
|
+
await fastify.close()
|
|
74
63
|
})
|
|
75
64
|
|
|
76
|
-
test('should be able to override the default plain text parser after removeAllContentTypeParsers', (t
|
|
77
|
-
t.plan(
|
|
65
|
+
test('should be able to override the default plain text parser after removeAllContentTypeParsers', async (t) => {
|
|
66
|
+
t.plan(4)
|
|
78
67
|
|
|
79
68
|
const fastify = Fastify()
|
|
80
69
|
|
|
@@ -91,28 +80,24 @@ test('should be able to override the default plain text parser after removeAllCo
|
|
|
91
80
|
})
|
|
92
81
|
})
|
|
93
82
|
|
|
94
|
-
fastify.listen({ port: 0 }
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
'Content-Type': 'text/plain'
|
|
103
|
-
}
|
|
104
|
-
}, (err, response, body) => {
|
|
105
|
-
t.assert.ifError(err)
|
|
106
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
107
|
-
t.assert.strictEqual(body.toString(), 'hello world')
|
|
108
|
-
fastify.close()
|
|
109
|
-
done()
|
|
110
|
-
})
|
|
83
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
84
|
+
|
|
85
|
+
const result = await fetch(fastifyServer, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
body: 'hello world',
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'text/plain'
|
|
90
|
+
}
|
|
111
91
|
})
|
|
92
|
+
|
|
93
|
+
t.assert.ok(result.ok)
|
|
94
|
+
t.assert.strictEqual(result.status, 200)
|
|
95
|
+
t.assert.strictEqual(await result.text(), 'hello world')
|
|
96
|
+
await fastify.close()
|
|
112
97
|
})
|
|
113
98
|
|
|
114
|
-
test('should be able to add a custom content type parser after removeAllContentTypeParsers', (t
|
|
115
|
-
t.plan(
|
|
99
|
+
test('should be able to add a custom content type parser after removeAllContentTypeParsers', async (t) => {
|
|
100
|
+
t.plan(4)
|
|
116
101
|
|
|
117
102
|
const fastify = Fastify()
|
|
118
103
|
|
|
@@ -128,22 +113,18 @@ test('should be able to add a custom content type parser after removeAllContentT
|
|
|
128
113
|
})
|
|
129
114
|
})
|
|
130
115
|
|
|
131
|
-
fastify.listen({ port: 0 }
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
'Content-Type': 'application/jsoff'
|
|
140
|
-
}
|
|
141
|
-
}, (err, response, body) => {
|
|
142
|
-
t.assert.ifError(err)
|
|
143
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
144
|
-
t.assert.deepStrictEqual(body.toString(), JSON.stringify({ hello: 'world' }))
|
|
145
|
-
fastify.close()
|
|
146
|
-
done()
|
|
147
|
-
})
|
|
116
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
117
|
+
|
|
118
|
+
const result = await fetch(fastifyServer, {
|
|
119
|
+
method: 'POST',
|
|
120
|
+
body: JSON.stringify({ hello: 'world' }),
|
|
121
|
+
headers: {
|
|
122
|
+
'Content-Type': 'application/jsoff'
|
|
123
|
+
}
|
|
148
124
|
})
|
|
125
|
+
|
|
126
|
+
t.assert.ok(result.ok)
|
|
127
|
+
t.assert.strictEqual(result.status, 200)
|
|
128
|
+
t.assert.deepStrictEqual(await result.text(), JSON.stringify({ hello: 'world' }))
|
|
129
|
+
await fastify.close()
|
|
149
130
|
})
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('node:test')
|
|
4
4
|
const querystring = require('node:querystring')
|
|
5
|
-
const sget = require('simple-get').concat
|
|
6
5
|
const Fastify = require('..')
|
|
7
|
-
const { waitForCb } = require('./toolkit')
|
|
8
6
|
|
|
9
|
-
test('Custom querystring parser', t => {
|
|
10
|
-
t.plan(
|
|
7
|
+
test('Custom querystring parser', async t => {
|
|
8
|
+
t.plan(7)
|
|
11
9
|
|
|
12
10
|
const fastify = Fastify({
|
|
13
11
|
querystringParser: function (str) {
|
|
@@ -24,36 +22,22 @@ test('Custom querystring parser', t => {
|
|
|
24
22
|
reply.send({ hello: 'world' })
|
|
25
23
|
})
|
|
26
24
|
|
|
27
|
-
const
|
|
25
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
26
|
+
t.after(() => fastify.close())
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const result = await fetch(`${fastifyServer}?foo=bar&baz=faz`)
|
|
29
|
+
t.assert.ok(result.ok)
|
|
30
|
+
t.assert.strictEqual(result.status, 200)
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}, (err, response, body) => {
|
|
37
|
-
t.assert.ifError(err)
|
|
38
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
39
|
-
completion.stepIn()
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
fastify.inject({
|
|
43
|
-
method: 'GET',
|
|
44
|
-
url: `${address}?foo=bar&baz=faz`
|
|
45
|
-
}, (err, response, body) => {
|
|
46
|
-
t.assert.ifError(err)
|
|
47
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
48
|
-
completion.stepIn()
|
|
49
|
-
})
|
|
32
|
+
const injectResponse = await fastify.inject({
|
|
33
|
+
method: 'GET',
|
|
34
|
+
url: `${fastifyServer}?foo=bar&baz=faz`
|
|
50
35
|
})
|
|
51
|
-
|
|
52
|
-
return completion.patience
|
|
36
|
+
t.assert.strictEqual(injectResponse.statusCode, 200)
|
|
53
37
|
})
|
|
54
38
|
|
|
55
|
-
test('Custom querystring parser should be called also if there is nothing to parse', t => {
|
|
56
|
-
t.plan(
|
|
39
|
+
test('Custom querystring parser should be called also if there is nothing to parse', async t => {
|
|
40
|
+
t.plan(7)
|
|
57
41
|
|
|
58
42
|
const fastify = Fastify({
|
|
59
43
|
querystringParser: function (str) {
|
|
@@ -67,36 +51,22 @@ test('Custom querystring parser should be called also if there is nothing to par
|
|
|
67
51
|
reply.send({ hello: 'world' })
|
|
68
52
|
})
|
|
69
53
|
|
|
70
|
-
const
|
|
54
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
55
|
+
t.after(() => fastify.close())
|
|
71
56
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
57
|
+
const result = await fetch(fastifyServer)
|
|
58
|
+
t.assert.ok(result.ok)
|
|
59
|
+
t.assert.strictEqual(result.status, 200)
|
|
75
60
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}, (err, response, body) => {
|
|
80
|
-
t.assert.ifError(err)
|
|
81
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
82
|
-
completion.stepIn()
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
fastify.inject({
|
|
86
|
-
method: 'GET',
|
|
87
|
-
url: address
|
|
88
|
-
}, (err, response, body) => {
|
|
89
|
-
t.assert.ifError(err)
|
|
90
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
91
|
-
completion.stepIn()
|
|
92
|
-
})
|
|
61
|
+
const injectResponse = await fastify.inject({
|
|
62
|
+
method: 'GET',
|
|
63
|
+
url: fastifyServer
|
|
93
64
|
})
|
|
94
|
-
|
|
95
|
-
return completion.patience
|
|
65
|
+
t.assert.strictEqual(injectResponse.statusCode, 200)
|
|
96
66
|
})
|
|
97
67
|
|
|
98
|
-
test('Querystring without value', t => {
|
|
99
|
-
t.plan(
|
|
68
|
+
test('Querystring without value', async t => {
|
|
69
|
+
t.plan(7)
|
|
100
70
|
|
|
101
71
|
const fastify = Fastify({
|
|
102
72
|
querystringParser: function (str) {
|
|
@@ -110,32 +80,18 @@ test('Querystring without value', t => {
|
|
|
110
80
|
reply.send({ hello: 'world' })
|
|
111
81
|
})
|
|
112
82
|
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
fastify.listen({ port: 0 }, (err, address) => {
|
|
116
|
-
t.assert.ifError(err)
|
|
117
|
-
t.after(() => fastify.close())
|
|
83
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
84
|
+
t.after(() => fastify.close())
|
|
118
85
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}, (err, response, body) => {
|
|
123
|
-
t.assert.ifError(err)
|
|
124
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
125
|
-
completion.stepIn()
|
|
126
|
-
})
|
|
86
|
+
const result = await fetch(`${fastifyServer}?foo`)
|
|
87
|
+
t.assert.ok(result.ok)
|
|
88
|
+
t.assert.strictEqual(result.status, 200)
|
|
127
89
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}, (err, response, body) => {
|
|
132
|
-
t.assert.ifError(err)
|
|
133
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
134
|
-
completion.stepIn()
|
|
135
|
-
})
|
|
90
|
+
const injectResponse = await fastify.inject({
|
|
91
|
+
method: 'GET',
|
|
92
|
+
url: `${fastifyServer}?foo`
|
|
136
93
|
})
|
|
137
|
-
|
|
138
|
-
return completion.patience
|
|
94
|
+
t.assert.strictEqual(injectResponse.statusCode, 200)
|
|
139
95
|
})
|
|
140
96
|
|
|
141
97
|
test('Custom querystring parser should be a function', t => {
|
|
@@ -153,3 +109,21 @@ test('Custom querystring parser should be a function', t => {
|
|
|
153
109
|
)
|
|
154
110
|
}
|
|
155
111
|
})
|
|
112
|
+
|
|
113
|
+
test('Custom querystring parser should be a function', t => {
|
|
114
|
+
t.plan(1)
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
Fastify({
|
|
118
|
+
routerOptions: {
|
|
119
|
+
querystringParser: 10
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
t.fail('Should throw')
|
|
123
|
+
} catch (err) {
|
|
124
|
+
t.assert.equal(
|
|
125
|
+
err.message,
|
|
126
|
+
"querystringParser option should be a function, instead got 'number'"
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
})
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/* eslint no-prototype-builtins: 0 */
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const test = t.test
|
|
5
|
+
const { test } = require('node:test')
|
|
7
6
|
const Fastify = require('..')
|
|
8
7
|
const fp = require('fastify-plugin')
|
|
9
8
|
|
|
@@ -24,8 +23,8 @@ test('plugin namespace', async t => {
|
|
|
24
23
|
}, { namepace: 'foo' })
|
|
25
24
|
|
|
26
25
|
// ! but outside the plugin the decorator would be app.foo.utility()
|
|
27
|
-
t.ok(app.foo.utility)
|
|
26
|
+
t.assert.ok(app.foo.utility)
|
|
28
27
|
|
|
29
28
|
const res = await app.inject('/')
|
|
30
|
-
t.
|
|
29
|
+
t.assert.deepStrictEqual(res.json(), { utility: 'utility' })
|
|
31
30
|
})
|