fastify 5.1.0 → 5.2.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/README.md +12 -7
- package/docs/Guides/Database.md +15 -15
- package/docs/Guides/Detecting-When-Clients-Abort.md +28 -28
- package/docs/Guides/Ecosystem.md +13 -7
- package/docs/Guides/Index.md +1 -1
- package/docs/Guides/Migration-Guide-V4.md +11 -11
- package/docs/Guides/Migration-Guide-V5.md +5 -5
- package/docs/Guides/Plugins-Guide.md +1 -1
- package/docs/Guides/Prototype-Poisoning.md +3 -3
- package/docs/Guides/Recommendations.md +9 -9
- package/docs/Guides/Serverless.md +5 -5
- package/docs/Guides/Testing.md +8 -8
- package/docs/Guides/Write-Plugin.md +1 -1
- package/docs/Guides/Write-Type-Provider.md +3 -3
- package/docs/Reference/Decorators.md +2 -2
- package/docs/Reference/Errors.md +2 -2
- package/docs/Reference/Hooks.md +7 -7
- package/docs/Reference/LTS.md +8 -0
- package/docs/Reference/Logging.md +5 -4
- package/docs/Reference/Reply.md +54 -53
- package/docs/Reference/Request.md +49 -43
- package/docs/Reference/Routes.md +7 -7
- package/docs/Reference/Server.md +31 -27
- package/docs/Reference/TypeScript.md +9 -9
- package/docs/Reference/Validation-and-Serialization.md +5 -5
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +4 -4
- package/fastify.js +1 -1
- package/lib/error-handler.js +9 -9
- package/lib/errors.js +1 -1
- package/lib/hooks.js +4 -1
- package/lib/request.js +11 -10
- package/package.json +3 -4
- package/test/{allowUnsafeRegex.test.js → allow-unsafe-regex.test.js} +4 -4
- package/test/async-dispose.test.js +0 -1
- package/test/async_hooks.test.js +4 -4
- package/test/buffer.test.js +4 -4
- package/test/build-certificate.js +1 -1
- package/test/bundler/README.md +5 -5
- package/test/case-insensitive.test.js +10 -10
- package/test/check.test.js +2 -3
- package/test/{childLoggerFactory.test.js → child-logger-factory.test.js} +1 -1
- package/test/client-timeout.test.js +1 -1
- package/test/close-pipelining.test.js +0 -1
- package/test/conditional-pino.test.js +3 -3
- package/test/content-length.test.js +53 -68
- package/test/content-parser.test.js +178 -167
- package/test/content-type.test.js +8 -9
- package/test/context-config.test.js +44 -54
- package/test/custom-parser.5.test.js +32 -32
- package/test/encapsulated-child-logger-factory.test.js +8 -8
- package/test/encapsulated-error-handler.test.js +20 -20
- package/test/fastify-instance.test.js +33 -34
- package/test/{findRoute.test.js → find-route.test.js} +11 -10
- package/test/fluent-schema.test.js +33 -36
- package/test/handler-context.test.js +11 -11
- package/test/has-route.test.js +12 -15
- package/test/header-overflow.test.js +13 -12
- package/test/hooks.on-ready.test.js +2 -2
- package/test/hooks.test.js +19 -19
- package/test/http-methods/head.test.js +0 -3
- package/test/imports.test.js +2 -2
- package/test/internals/errors.test.js +1 -1
- package/test/listen.5.test.js +9 -9
- package/test/{maxRequestsPerSocket.test.js → max-requests-per-socket.test.js} +30 -30
- package/test/middleware.test.js +4 -5
- package/test/noop-set.test.js +1 -1
- package/test/post-empty-body.test.js +18 -11
- package/test/pretty-print.test.js +59 -49
- package/test/proto-poisoning.test.js +42 -37
- package/test/reply-code.test.js +34 -32
- package/test/{reply-earlyHints.test.js → reply-early-hints.test.js} +21 -19
- package/test/request-header-host.test.js +154 -12
- package/test/request-id.test.js +31 -25
- package/test/{requestTimeout.test.js → request-timeout.test.js} +11 -11
- package/test/route.3.test.js +3 -2
- package/test/route.8.test.js +20 -20
- package/test/router-options.test.js +80 -77
- package/test/schema-examples.test.js +72 -38
- package/test/server.test.js +12 -12
- package/test/set-error-handler.test.js +2 -3
- package/test/stream-serializers.test.js +10 -7
- package/test/sync-routes.test.js +18 -18
- package/test/trust-proxy.test.js +51 -45
- package/test/type-provider.test.js +8 -6
- package/test/types/content-type-parser.test-d.ts +1 -1
- package/test/types/fastify.test-d.ts +4 -4
- package/test/types/instance.test-d.ts +3 -1
- package/test/types/logger.test-d.ts +2 -2
- package/test/types/plugin.test-d.ts +2 -2
- package/test/types/register.test-d.ts +2 -2
- package/test/types/reply.test-d.ts +1 -1
- package/test/types/route.test-d.ts +1 -1
- package/test/types/serverFactory.test-d.ts +1 -1
- package/test/types/type-provider.test-d.ts +1 -1
- package/test/url-rewriting.test.js +35 -38
- package/test/{useSemicolonDelimiter.test.js → use-semicolon-delimiter.test.js} +30 -30
- package/test/validation-error-handling.test.js +259 -285
- package/types/hooks.d.ts +1 -1
- package/types/instance.d.ts +9 -2
- package/types/reply.d.ts +1 -1
- package/types/request.d.ts +0 -4
- package/types/serverFactory.d.ts +3 -3
- package/types/utils.d.ts +3 -3
- /package/test/{connectionTimeout.test.js → connection-timeout.test.js} +0 -0
- /package/test/internals/{contentTypeParser.test.js → content-type-parser.test.js} +0 -0
- /package/test/internals/{handleRequest.test.js → handle-request.test.js} +0 -0
- /package/test/internals/{hookRunner.test.js → hook-runner.test.js} +0 -0
- /package/test/internals/{initialConfig.test.js → initial-config.test.js} +0 -0
- /package/test/internals/{reqIdGenFactory.test.js → req-id-gen-factory.test.js} +0 -0
- /package/test/{wrapThenable.test.js → wrap-thenable.test.js} +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const test = t.test
|
|
3
|
+
const { test } = require('node:test')
|
|
5
4
|
const Fastify = require('..')
|
|
6
5
|
const keys = require('../lib/symbols')
|
|
7
6
|
const { FST_ERR_CTP_ALREADY_PRESENT, FST_ERR_CTP_INVALID_TYPE, FST_ERR_CTP_INVALID_MEDIA_TYPE } = require('../lib/errors')
|
|
@@ -10,21 +9,22 @@ const first = function (req, payload, done) {}
|
|
|
10
9
|
const second = function (req, payload, done) {}
|
|
11
10
|
const third = function (req, payload, done) {}
|
|
12
11
|
|
|
13
|
-
test('hasContentTypeParser', t => {
|
|
14
|
-
test('should know about internal parsers', t => {
|
|
12
|
+
test('hasContentTypeParser', async t => {
|
|
13
|
+
await t.test('should know about internal parsers', (t, done) => {
|
|
15
14
|
t.plan(5)
|
|
16
15
|
|
|
17
16
|
const fastify = Fastify()
|
|
18
17
|
fastify.ready(err => {
|
|
19
|
-
t.
|
|
20
|
-
t.ok(fastify.hasContentTypeParser('application/json'))
|
|
21
|
-
t.ok(fastify.hasContentTypeParser('text/plain'))
|
|
22
|
-
t.ok(fastify.hasContentTypeParser(' text/plain '))
|
|
23
|
-
t.
|
|
18
|
+
t.assert.ifError(err)
|
|
19
|
+
t.assert.ok(fastify.hasContentTypeParser('application/json'))
|
|
20
|
+
t.assert.ok(fastify.hasContentTypeParser('text/plain'))
|
|
21
|
+
t.assert.ok(fastify.hasContentTypeParser(' text/plain '))
|
|
22
|
+
t.assert.ok(!fastify.hasContentTypeParser('application/jsoff'))
|
|
23
|
+
done()
|
|
24
24
|
})
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
-
test('should only work with string and RegExp', t => {
|
|
27
|
+
await t.test('should only work with string and RegExp', t => {
|
|
28
28
|
t.plan(8)
|
|
29
29
|
|
|
30
30
|
const fastify = Fastify()
|
|
@@ -32,21 +32,22 @@ test('hasContentTypeParser', t => {
|
|
|
32
32
|
fastify.addContentTypeParser(/^application\/.+\+xml/, first)
|
|
33
33
|
fastify.addContentTypeParser('image/gif', first)
|
|
34
34
|
|
|
35
|
-
t.ok(fastify.hasContentTypeParser('application/json'))
|
|
36
|
-
t.ok(fastify.hasContentTypeParser(/^image\/.*/))
|
|
37
|
-
t.ok(fastify.hasContentTypeParser(/^application\/.+\+xml/))
|
|
38
|
-
t.ok(fastify.hasContentTypeParser('image/gif'))
|
|
39
|
-
t.
|
|
40
|
-
t.
|
|
41
|
-
t.
|
|
42
|
-
t.throws(
|
|
35
|
+
t.assert.ok(fastify.hasContentTypeParser('application/json'))
|
|
36
|
+
t.assert.ok(fastify.hasContentTypeParser(/^image\/.*/))
|
|
37
|
+
t.assert.ok(fastify.hasContentTypeParser(/^application\/.+\+xml/))
|
|
38
|
+
t.assert.ok(fastify.hasContentTypeParser('image/gif'))
|
|
39
|
+
t.assert.ok(!fastify.hasContentTypeParser(/^image\/.+\+xml/))
|
|
40
|
+
t.assert.ok(!fastify.hasContentTypeParser('image/png'))
|
|
41
|
+
t.assert.ok(!fastify.hasContentTypeParser('*'))
|
|
42
|
+
t.assert.throws(
|
|
43
|
+
() => fastify.hasContentTypeParser(123),
|
|
44
|
+
FST_ERR_CTP_INVALID_TYPE
|
|
45
|
+
)
|
|
43
46
|
})
|
|
44
|
-
|
|
45
|
-
t.end()
|
|
46
47
|
})
|
|
47
48
|
|
|
48
|
-
test('getParser', t => {
|
|
49
|
-
test('should return matching parser', t => {
|
|
49
|
+
test('getParser', async t => {
|
|
50
|
+
await t.test('should return matching parser', t => {
|
|
50
51
|
t.plan(6)
|
|
51
52
|
|
|
52
53
|
const fastify = Fastify()
|
|
@@ -55,62 +56,62 @@ test('getParser', t => {
|
|
|
55
56
|
fastify.addContentTypeParser(/^application\/.+\+xml/, second)
|
|
56
57
|
fastify.addContentTypeParser('text/html', third)
|
|
57
58
|
|
|
58
|
-
t.
|
|
59
|
-
t.
|
|
60
|
-
t.
|
|
61
|
-
t.
|
|
62
|
-
t.
|
|
63
|
-
t.
|
|
59
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('application/t+xml').fn, second)
|
|
60
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('image/png').fn, first)
|
|
61
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html').fn, third)
|
|
62
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html; charset=utf-8').fn, third)
|
|
63
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html ; charset=utf-8').fn, third)
|
|
64
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/htmlINVALID')?.fn, undefined)
|
|
64
65
|
})
|
|
65
66
|
|
|
66
|
-
test('should return matching parser with caching /1', t => {
|
|
67
|
+
await t.test('should return matching parser with caching /1', t => {
|
|
67
68
|
t.plan(6)
|
|
68
69
|
|
|
69
70
|
const fastify = Fastify()
|
|
70
71
|
|
|
71
72
|
fastify.addContentTypeParser('text/html', first)
|
|
72
73
|
|
|
73
|
-
t.
|
|
74
|
-
t.
|
|
75
|
-
t.
|
|
76
|
-
t.
|
|
77
|
-
t.
|
|
78
|
-
t.
|
|
74
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html').fn, first)
|
|
75
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 0)
|
|
76
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html ').fn, first)
|
|
77
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 1)
|
|
78
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html ').fn, first)
|
|
79
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 1)
|
|
79
80
|
})
|
|
80
81
|
|
|
81
|
-
test('should return matching parser with caching /2', t => {
|
|
82
|
+
await t.test('should return matching parser with caching /2', t => {
|
|
82
83
|
t.plan(8)
|
|
83
84
|
|
|
84
85
|
const fastify = Fastify()
|
|
85
86
|
|
|
86
87
|
fastify.addContentTypeParser('text/html', first)
|
|
87
88
|
|
|
88
|
-
t.
|
|
89
|
-
t.
|
|
90
|
-
t.
|
|
91
|
-
t.
|
|
92
|
-
t.
|
|
93
|
-
t.
|
|
94
|
-
t.
|
|
95
|
-
t.
|
|
89
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html').fn, first)
|
|
90
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 0)
|
|
91
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/HTML').fn, first)
|
|
92
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 1)
|
|
93
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('TEXT/html').fn, first)
|
|
94
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 2)
|
|
95
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('TEXT/html').fn, first)
|
|
96
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 2)
|
|
96
97
|
})
|
|
97
98
|
|
|
98
|
-
test('should return matching parser with caching /3', t => {
|
|
99
|
+
await t.test('should return matching parser with caching /3', t => {
|
|
99
100
|
t.plan(6)
|
|
100
101
|
|
|
101
102
|
const fastify = Fastify()
|
|
102
103
|
|
|
103
104
|
fastify.addContentTypeParser(/^text\/html(;\s*charset=[^;]+)?$/, first)
|
|
104
105
|
|
|
105
|
-
t.
|
|
106
|
-
t.
|
|
107
|
-
t.
|
|
108
|
-
t.
|
|
109
|
-
t.
|
|
110
|
-
t.
|
|
106
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html').fn, first)
|
|
107
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 1)
|
|
108
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html;charset=utf-8').fn, first)
|
|
109
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 2)
|
|
110
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html;charset=utf-8').fn, first)
|
|
111
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].cache.size, 2)
|
|
111
112
|
})
|
|
112
113
|
|
|
113
|
-
test('should prefer content type parser with string value', t => {
|
|
114
|
+
await t.test('should prefer content type parser with string value', t => {
|
|
114
115
|
t.plan(2)
|
|
115
116
|
|
|
116
117
|
const fastify = Fastify()
|
|
@@ -118,11 +119,11 @@ test('getParser', t => {
|
|
|
118
119
|
fastify.addContentTypeParser(/^image\/.*/, first)
|
|
119
120
|
fastify.addContentTypeParser('image/gif', second)
|
|
120
121
|
|
|
121
|
-
t.
|
|
122
|
-
t.
|
|
122
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('image/gif').fn, second)
|
|
123
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('image/png').fn, first)
|
|
123
124
|
})
|
|
124
125
|
|
|
125
|
-
test('should return parser that catches all if no other is set', t => {
|
|
126
|
+
await t.test('should return parser that catches all if no other is set', t => {
|
|
126
127
|
t.plan(3)
|
|
127
128
|
|
|
128
129
|
const fastify = Fastify()
|
|
@@ -130,12 +131,12 @@ test('getParser', t => {
|
|
|
130
131
|
fastify.addContentTypeParser('*', first)
|
|
131
132
|
fastify.addContentTypeParser(/^text\/.*/, second)
|
|
132
133
|
|
|
133
|
-
t.
|
|
134
|
-
t.
|
|
135
|
-
t.
|
|
134
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('image/gif').fn, first)
|
|
135
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text/html').fn, second)
|
|
136
|
+
t.assert.strictEqual(fastify[keys.kContentTypeParser].getParser('text').fn, first)
|
|
136
137
|
})
|
|
137
138
|
|
|
138
|
-
test('should return undefined if no matching parser exist', t => {
|
|
139
|
+
await t.test('should return undefined if no matching parser exist', t => {
|
|
139
140
|
t.plan(2)
|
|
140
141
|
|
|
141
142
|
const fastify = Fastify()
|
|
@@ -143,15 +144,13 @@ test('getParser', t => {
|
|
|
143
144
|
fastify.addContentTypeParser(/^weirdType\/.+/, first)
|
|
144
145
|
fastify.addContentTypeParser('application/javascript', first)
|
|
145
146
|
|
|
146
|
-
t.
|
|
147
|
-
t.
|
|
147
|
+
t.assert.ok(!fastify[keys.kContentTypeParser].getParser('application/xml'))
|
|
148
|
+
t.assert.ok(!fastify[keys.kContentTypeParser].getParser('weirdType/'))
|
|
148
149
|
})
|
|
149
|
-
|
|
150
|
-
t.end()
|
|
151
150
|
})
|
|
152
151
|
|
|
153
|
-
test('existingParser', t => {
|
|
154
|
-
test('returns always false for "*"', t => {
|
|
152
|
+
test('existingParser', async t => {
|
|
153
|
+
await t.test('returns always false for "*"', t => {
|
|
155
154
|
t.plan(2)
|
|
156
155
|
|
|
157
156
|
const fastify = Fastify()
|
|
@@ -160,14 +159,14 @@ test('existingParser', t => {
|
|
|
160
159
|
fastify.addContentTypeParser(/^application\/.+\+xml/, first)
|
|
161
160
|
fastify.addContentTypeParser('text/html', first)
|
|
162
161
|
|
|
163
|
-
t.
|
|
162
|
+
t.assert.ok(!fastify[keys.kContentTypeParser].existingParser('*'))
|
|
164
163
|
|
|
165
164
|
fastify.addContentTypeParser('*', first)
|
|
166
165
|
|
|
167
|
-
t.
|
|
166
|
+
t.assert.ok(!fastify[keys.kContentTypeParser].existingParser('*'))
|
|
168
167
|
})
|
|
169
168
|
|
|
170
|
-
test('let you override the default parser once', t => {
|
|
169
|
+
await t.test('let you override the default parser once', t => {
|
|
171
170
|
t.plan(2)
|
|
172
171
|
|
|
173
172
|
const fastify = Fastify()
|
|
@@ -175,15 +174,13 @@ test('existingParser', t => {
|
|
|
175
174
|
fastify.addContentTypeParser('application/json', first)
|
|
176
175
|
fastify.addContentTypeParser('text/plain', first)
|
|
177
176
|
|
|
178
|
-
t.throws(
|
|
177
|
+
t.assert.throws(
|
|
179
178
|
() => fastify.addContentTypeParser('application/json', first),
|
|
180
|
-
FST_ERR_CTP_ALREADY_PRESENT
|
|
181
|
-
"Content type parser 'application/json' already present"
|
|
179
|
+
FST_ERR_CTP_ALREADY_PRESENT
|
|
182
180
|
)
|
|
183
|
-
t.throws(
|
|
181
|
+
t.assert.throws(
|
|
184
182
|
() => fastify.addContentTypeParser('text/plain', first),
|
|
185
|
-
FST_ERR_CTP_ALREADY_PRESENT
|
|
186
|
-
"Content type parser 'text/plain' already present"
|
|
183
|
+
FST_ERR_CTP_ALREADY_PRESENT
|
|
187
184
|
)
|
|
188
185
|
})
|
|
189
186
|
|
|
@@ -194,49 +191,47 @@ test('existingParser', t => {
|
|
|
194
191
|
fastify.addContentTypeParser(/^application\/.+\+xml/, first)
|
|
195
192
|
fastify.addContentTypeParser('text/html', first)
|
|
196
193
|
|
|
197
|
-
t.ok(contentTypeParser.existingParser(/^image\/.*/))
|
|
198
|
-
t.ok(contentTypeParser.existingParser('text/html'))
|
|
199
|
-
t.ok(contentTypeParser.existingParser(/^application\/.+\+xml/))
|
|
200
|
-
t.
|
|
201
|
-
t.
|
|
202
|
-
t.
|
|
203
|
-
t.
|
|
204
|
-
|
|
205
|
-
t.end()
|
|
194
|
+
t.assert.ok(contentTypeParser.existingParser(/^image\/.*/))
|
|
195
|
+
t.assert.ok(contentTypeParser.existingParser('text/html'))
|
|
196
|
+
t.assert.ok(contentTypeParser.existingParser(/^application\/.+\+xml/))
|
|
197
|
+
t.assert.ok(!contentTypeParser.existingParser('application/json'))
|
|
198
|
+
t.assert.ok(!contentTypeParser.existingParser('text/plain'))
|
|
199
|
+
t.assert.ok(!contentTypeParser.existingParser('image/png'))
|
|
200
|
+
t.assert.ok(!contentTypeParser.existingParser(/^application\/.+\+json/))
|
|
206
201
|
})
|
|
207
202
|
|
|
208
|
-
test('add', t => {
|
|
209
|
-
test('should only accept string and RegExp', t => {
|
|
203
|
+
test('add', async t => {
|
|
204
|
+
await t.test('should only accept string and RegExp', t => {
|
|
210
205
|
t.plan(4)
|
|
211
206
|
|
|
212
207
|
const fastify = Fastify()
|
|
213
208
|
const contentTypeParser = fastify[keys.kContentTypeParser]
|
|
214
209
|
|
|
215
|
-
t.
|
|
216
|
-
t.
|
|
217
|
-
t.throws(
|
|
210
|
+
t.assert.ifError(contentTypeParser.add('test', {}, first))
|
|
211
|
+
t.assert.ifError(contentTypeParser.add(/test/, {}, first))
|
|
212
|
+
t.assert.throws(
|
|
218
213
|
() => contentTypeParser.add({}, {}, first),
|
|
219
214
|
FST_ERR_CTP_INVALID_TYPE,
|
|
220
215
|
'The content type should be a string or a RegExp'
|
|
221
216
|
)
|
|
222
|
-
t.throws(
|
|
217
|
+
t.assert.throws(
|
|
223
218
|
() => contentTypeParser.add(1, {}, first),
|
|
224
219
|
FST_ERR_CTP_INVALID_TYPE,
|
|
225
220
|
'The content type should be a string or a RegExp'
|
|
226
221
|
)
|
|
227
222
|
})
|
|
228
223
|
|
|
229
|
-
test('should set "*" as parser that catches all', t => {
|
|
224
|
+
await t.test('should set "*" as parser that catches all', t => {
|
|
230
225
|
t.plan(1)
|
|
231
226
|
|
|
232
227
|
const fastify = Fastify()
|
|
233
228
|
const contentTypeParser = fastify[keys.kContentTypeParser]
|
|
234
229
|
|
|
235
230
|
contentTypeParser.add('*', {}, first)
|
|
236
|
-
t.
|
|
231
|
+
t.assert.strictEqual(contentTypeParser.customParsers.get('').fn, first)
|
|
237
232
|
})
|
|
238
233
|
|
|
239
|
-
test('should lowercase contentTypeParser name', async t => {
|
|
234
|
+
await t.test('should lowercase contentTypeParser name', async t => {
|
|
240
235
|
t.plan(1)
|
|
241
236
|
const fastify = Fastify()
|
|
242
237
|
fastify.addContentTypeParser('text/html', function (req, done) {
|
|
@@ -247,11 +242,11 @@ test('add', t => {
|
|
|
247
242
|
done()
|
|
248
243
|
})
|
|
249
244
|
} catch (err) {
|
|
250
|
-
t.
|
|
245
|
+
t.assert.strictEqual(err.message, FST_ERR_CTP_ALREADY_PRESENT('text/html').message)
|
|
251
246
|
}
|
|
252
247
|
})
|
|
253
248
|
|
|
254
|
-
test('should trim contentTypeParser name', async t => {
|
|
249
|
+
await t.test('should trim contentTypeParser name', async t => {
|
|
255
250
|
t.plan(1)
|
|
256
251
|
const fastify = Fastify()
|
|
257
252
|
fastify.addContentTypeParser('text/html', function (req, done) {
|
|
@@ -262,14 +257,12 @@ test('add', t => {
|
|
|
262
257
|
done()
|
|
263
258
|
})
|
|
264
259
|
} catch (err) {
|
|
265
|
-
t.
|
|
260
|
+
t.assert.strictEqual(err.message, FST_ERR_CTP_ALREADY_PRESENT('text/html').message)
|
|
266
261
|
}
|
|
267
262
|
})
|
|
268
|
-
|
|
269
|
-
t.end()
|
|
270
263
|
})
|
|
271
264
|
|
|
272
|
-
test('non-Error thrown from content parser is properly handled', t => {
|
|
265
|
+
test('non-Error thrown from content parser is properly handled', (t, done) => {
|
|
273
266
|
t.plan(3)
|
|
274
267
|
|
|
275
268
|
const fastify = Fastify()
|
|
@@ -285,7 +278,7 @@ test('non-Error thrown from content parser is properly handled', t => {
|
|
|
285
278
|
})
|
|
286
279
|
|
|
287
280
|
fastify.setErrorHandler((err, req, res) => {
|
|
288
|
-
t.
|
|
281
|
+
t.assert.strictEqual(err, throwable)
|
|
289
282
|
|
|
290
283
|
res.send(payload)
|
|
291
284
|
})
|
|
@@ -296,12 +289,13 @@ test('non-Error thrown from content parser is properly handled', t => {
|
|
|
296
289
|
headers: { 'Content-Type': 'text/test' },
|
|
297
290
|
body: 'some text'
|
|
298
291
|
}, (err, res) => {
|
|
299
|
-
t.
|
|
300
|
-
t.
|
|
292
|
+
t.assert.ifError(err)
|
|
293
|
+
t.assert.strictEqual(res.payload, payload)
|
|
294
|
+
done()
|
|
301
295
|
})
|
|
302
296
|
})
|
|
303
297
|
|
|
304
|
-
test('Error thrown 415 from content type is null and make post request to server', t => {
|
|
298
|
+
test('Error thrown 415 from content type is null and make post request to server', (t, done) => {
|
|
305
299
|
t.plan(3)
|
|
306
300
|
|
|
307
301
|
const fastify = Fastify()
|
|
@@ -315,28 +309,29 @@ test('Error thrown 415 from content type is null and make post request to server
|
|
|
315
309
|
url: '/',
|
|
316
310
|
body: 'some text'
|
|
317
311
|
}, (err, res) => {
|
|
318
|
-
t.
|
|
319
|
-
t.
|
|
320
|
-
t.
|
|
312
|
+
t.assert.ifError(err)
|
|
313
|
+
t.assert.strictEqual(res.statusCode, 415)
|
|
314
|
+
t.assert.strictEqual(JSON.parse(res.body).message, errMsg)
|
|
315
|
+
done()
|
|
321
316
|
})
|
|
322
317
|
})
|
|
323
318
|
|
|
324
|
-
test('remove', t => {
|
|
325
|
-
test('should remove default parser', t => {
|
|
319
|
+
test('remove', async t => {
|
|
320
|
+
await t.test('should remove default parser', t => {
|
|
326
321
|
t.plan(6)
|
|
327
322
|
|
|
328
323
|
const fastify = Fastify()
|
|
329
324
|
const contentTypeParser = fastify[keys.kContentTypeParser]
|
|
330
325
|
|
|
331
|
-
t.ok(contentTypeParser.remove('application/json'))
|
|
332
|
-
t.
|
|
333
|
-
t.
|
|
334
|
-
t.ok(contentTypeParser.remove(' text/plain '))
|
|
335
|
-
t.
|
|
336
|
-
t.
|
|
326
|
+
t.assert.ok(contentTypeParser.remove('application/json'))
|
|
327
|
+
t.assert.ok(!contentTypeParser.customParsers['application/json'])
|
|
328
|
+
t.assert.ok(!contentTypeParser.parserList.find(parser => parser === 'application/json'))
|
|
329
|
+
t.assert.ok(contentTypeParser.remove(' text/plain '))
|
|
330
|
+
t.assert.ok(!contentTypeParser.customParsers['text/plain'])
|
|
331
|
+
t.assert.ok(!contentTypeParser.parserList.find(parser => parser === 'text/plain'))
|
|
337
332
|
})
|
|
338
333
|
|
|
339
|
-
test('should remove RegExp parser', t => {
|
|
334
|
+
await t.test('should remove RegExp parser', t => {
|
|
340
335
|
t.plan(3)
|
|
341
336
|
|
|
342
337
|
const fastify = Fastify()
|
|
@@ -344,39 +339,37 @@ test('remove', t => {
|
|
|
344
339
|
|
|
345
340
|
const contentTypeParser = fastify[keys.kContentTypeParser]
|
|
346
341
|
|
|
347
|
-
t.ok(contentTypeParser.remove(/^text\/*/))
|
|
348
|
-
t.
|
|
349
|
-
t.
|
|
342
|
+
t.assert.ok(contentTypeParser.remove(/^text\/*/))
|
|
343
|
+
t.assert.ok(!contentTypeParser.customParsers[/^text\/*/])
|
|
344
|
+
t.assert.ok(!contentTypeParser.parserRegExpList.find(parser => parser.toString() === /^text\/*/.toString()))
|
|
350
345
|
})
|
|
351
346
|
|
|
352
|
-
test('should throw an error if content type is neither string nor RegExp', t => {
|
|
347
|
+
await t.test('should throw an error if content type is neither string nor RegExp', t => {
|
|
353
348
|
t.plan(1)
|
|
354
349
|
|
|
355
350
|
const fastify = Fastify()
|
|
356
351
|
|
|
357
|
-
t.throws(() => fastify[keys.kContentTypeParser].remove(12), FST_ERR_CTP_INVALID_TYPE)
|
|
352
|
+
t.assert.throws(() => fastify[keys.kContentTypeParser].remove(12), FST_ERR_CTP_INVALID_TYPE)
|
|
358
353
|
})
|
|
359
354
|
|
|
360
|
-
test('should return false if content type does not exist', t => {
|
|
355
|
+
await t.test('should return false if content type does not exist', t => {
|
|
361
356
|
t.plan(1)
|
|
362
357
|
|
|
363
358
|
const fastify = Fastify()
|
|
364
359
|
|
|
365
|
-
t.
|
|
360
|
+
t.assert.ok(!fastify[keys.kContentTypeParser].remove('image/png'))
|
|
366
361
|
})
|
|
367
362
|
|
|
368
|
-
test('should not remove any content type parser if content type does not exist', t => {
|
|
363
|
+
await t.test('should not remove any content type parser if content type does not exist', t => {
|
|
369
364
|
t.plan(2)
|
|
370
365
|
|
|
371
366
|
const fastify = Fastify()
|
|
372
367
|
|
|
373
368
|
const contentTypeParser = fastify[keys.kContentTypeParser]
|
|
374
369
|
|
|
375
|
-
t.
|
|
376
|
-
t.
|
|
370
|
+
t.assert.ok(!contentTypeParser.remove('image/png'))
|
|
371
|
+
t.assert.strictEqual(contentTypeParser.customParsers.size, 2)
|
|
377
372
|
})
|
|
378
|
-
|
|
379
|
-
t.end()
|
|
380
373
|
})
|
|
381
374
|
|
|
382
375
|
test('remove all should remove all existing parsers and reset cache', t => {
|
|
@@ -391,10 +384,10 @@ test('remove all should remove all existing parsers and reset cache', t => {
|
|
|
391
384
|
contentTypeParser.getParser('application/xml') // fill cache with one entry
|
|
392
385
|
contentTypeParser.removeAll()
|
|
393
386
|
|
|
394
|
-
t.
|
|
395
|
-
t.
|
|
396
|
-
t.
|
|
397
|
-
t.
|
|
387
|
+
t.assert.strictEqual(contentTypeParser.cache.size, 0)
|
|
388
|
+
t.assert.strictEqual(contentTypeParser.parserList.length, 0)
|
|
389
|
+
t.assert.strictEqual(contentTypeParser.parserRegExpList.length, 0)
|
|
390
|
+
t.assert.strictEqual(Object.keys(contentTypeParser.customParsers).length, 0)
|
|
398
391
|
})
|
|
399
392
|
|
|
400
393
|
test('Safeguard against malicious content-type / 1', async t => {
|
|
@@ -417,7 +410,7 @@ test('Safeguard against malicious content-type / 1', async t => {
|
|
|
417
410
|
body: ''
|
|
418
411
|
})
|
|
419
412
|
|
|
420
|
-
t.
|
|
413
|
+
t.assert.strictEqual(response.statusCode, 415)
|
|
421
414
|
}
|
|
422
415
|
})
|
|
423
416
|
|
|
@@ -439,7 +432,7 @@ test('Safeguard against malicious content-type / 2', async t => {
|
|
|
439
432
|
body: ''
|
|
440
433
|
})
|
|
441
434
|
|
|
442
|
-
t.
|
|
435
|
+
t.assert.strictEqual(response.statusCode, 415)
|
|
443
436
|
})
|
|
444
437
|
|
|
445
438
|
test('Safeguard against malicious content-type / 3', async t => {
|
|
@@ -460,7 +453,7 @@ test('Safeguard against malicious content-type / 3', async t => {
|
|
|
460
453
|
body: ''
|
|
461
454
|
})
|
|
462
455
|
|
|
463
|
-
t.
|
|
456
|
+
t.assert.strictEqual(response.statusCode, 415)
|
|
464
457
|
})
|
|
465
458
|
|
|
466
459
|
test('Safeguard against content-type spoofing - string', async t => {
|
|
@@ -469,11 +462,11 @@ test('Safeguard against content-type spoofing - string', async t => {
|
|
|
469
462
|
const fastify = Fastify()
|
|
470
463
|
fastify.removeAllContentTypeParsers()
|
|
471
464
|
fastify.addContentTypeParser('text/plain', function (request, body, done) {
|
|
472
|
-
t.
|
|
465
|
+
t.assert.ok('should be called')
|
|
473
466
|
done(null, body)
|
|
474
467
|
})
|
|
475
468
|
fastify.addContentTypeParser('application/json', function (request, body, done) {
|
|
476
|
-
t.fail('shouldn\'t be called')
|
|
469
|
+
t.assert.fail('shouldn\'t be called')
|
|
477
470
|
done(null, body)
|
|
478
471
|
})
|
|
479
472
|
|
|
@@ -491,24 +484,42 @@ test('Safeguard against content-type spoofing - string', async t => {
|
|
|
491
484
|
})
|
|
492
485
|
})
|
|
493
486
|
|
|
494
|
-
test('Warning against improper content-type - regexp', t => {
|
|
495
|
-
t.
|
|
496
|
-
|
|
497
|
-
|
|
487
|
+
test('Warning against improper content-type - regexp', async t => {
|
|
488
|
+
await t.test('improper regex - text plain', (t, done) => {
|
|
489
|
+
t.plan(2)
|
|
490
|
+
const fastify = Fastify()
|
|
498
491
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
492
|
+
process.on('warning', onWarning)
|
|
493
|
+
function onWarning (warning) {
|
|
494
|
+
t.assert.strictEqual(warning.name, 'FastifySecurity')
|
|
495
|
+
t.assert.strictEqual(warning.code, 'FSTSEC001')
|
|
496
|
+
done()
|
|
497
|
+
}
|
|
498
|
+
t.after(() => process.removeListener('warning', onWarning))
|
|
505
499
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
500
|
+
fastify.removeAllContentTypeParsers()
|
|
501
|
+
fastify.addContentTypeParser(/text\/plain/, function (request, body, done) {
|
|
502
|
+
done(null, body)
|
|
503
|
+
})
|
|
509
504
|
})
|
|
510
|
-
|
|
511
|
-
|
|
505
|
+
|
|
506
|
+
await t.test('improper regex - application json', (t, done) => {
|
|
507
|
+
t.plan(2)
|
|
508
|
+
const fastify = Fastify()
|
|
509
|
+
|
|
510
|
+
process.on('warning', onWarning)
|
|
511
|
+
function onWarning (warning) {
|
|
512
|
+
t.assert.strictEqual(warning.name, 'FastifySecurity')
|
|
513
|
+
t.assert.strictEqual(warning.code, 'FSTSEC001')
|
|
514
|
+
done()
|
|
515
|
+
}
|
|
516
|
+
t.after(() => process.removeListener('warning', onWarning))
|
|
517
|
+
|
|
518
|
+
fastify.removeAllContentTypeParsers()
|
|
519
|
+
|
|
520
|
+
fastify.addContentTypeParser(/application\/json/, function (request, body, done) {
|
|
521
|
+
done(null, body)
|
|
522
|
+
})
|
|
512
523
|
})
|
|
513
524
|
})
|
|
514
525
|
|
|
@@ -518,11 +529,11 @@ test('content-type match parameters - string 1', async t => {
|
|
|
518
529
|
const fastify = Fastify()
|
|
519
530
|
fastify.removeAllContentTypeParsers()
|
|
520
531
|
fastify.addContentTypeParser('text/plain; charset=utf8', function (request, body, done) {
|
|
521
|
-
t.fail('shouldn\'t be called')
|
|
532
|
+
t.assert.fail('shouldn\'t be called')
|
|
522
533
|
done(null, body)
|
|
523
534
|
})
|
|
524
535
|
fastify.addContentTypeParser('application/json; charset=utf8', function (request, body, done) {
|
|
525
|
-
t.
|
|
536
|
+
t.assert.ok('should be called')
|
|
526
537
|
done(null, body)
|
|
527
538
|
})
|
|
528
539
|
|
|
@@ -546,7 +557,7 @@ test('content-type match parameters - regexp', async t => {
|
|
|
546
557
|
const fastify = Fastify()
|
|
547
558
|
fastify.removeAllContentTypeParsers()
|
|
548
559
|
fastify.addContentTypeParser(/application\/json; charset=utf8/, function (request, body, done) {
|
|
549
|
-
t.
|
|
560
|
+
t.assert.ok('should be called')
|
|
550
561
|
done(null, body)
|
|
551
562
|
})
|
|
552
563
|
|
|
@@ -570,7 +581,7 @@ test('content-type fail when parameters not match - string 1', async t => {
|
|
|
570
581
|
const fastify = Fastify()
|
|
571
582
|
fastify.removeAllContentTypeParsers()
|
|
572
583
|
fastify.addContentTypeParser('application/json; charset=utf8; foo=bar', function (request, body, done) {
|
|
573
|
-
t.fail('shouldn\'t be called')
|
|
584
|
+
t.assert.fail('shouldn\'t be called')
|
|
574
585
|
done(null, body)
|
|
575
586
|
})
|
|
576
587
|
|
|
@@ -587,7 +598,7 @@ test('content-type fail when parameters not match - string 1', async t => {
|
|
|
587
598
|
body: ''
|
|
588
599
|
})
|
|
589
600
|
|
|
590
|
-
t.
|
|
601
|
+
t.assert.strictEqual(response.statusCode, 415)
|
|
591
602
|
})
|
|
592
603
|
|
|
593
604
|
test('content-type fail when parameters not match - string 2', async t => {
|
|
@@ -596,7 +607,7 @@ test('content-type fail when parameters not match - string 2', async t => {
|
|
|
596
607
|
const fastify = Fastify()
|
|
597
608
|
fastify.removeAllContentTypeParsers()
|
|
598
609
|
fastify.addContentTypeParser('application/json; charset=utf8; foo=bar', function (request, body, done) {
|
|
599
|
-
t.fail('shouldn\'t be called')
|
|
610
|
+
t.assert.fail('shouldn\'t be called')
|
|
600
611
|
done(null, body)
|
|
601
612
|
})
|
|
602
613
|
|
|
@@ -613,7 +624,7 @@ test('content-type fail when parameters not match - string 2', async t => {
|
|
|
613
624
|
body: ''
|
|
614
625
|
})
|
|
615
626
|
|
|
616
|
-
t.
|
|
627
|
+
t.assert.strictEqual(response.statusCode, 415)
|
|
617
628
|
})
|
|
618
629
|
|
|
619
630
|
test('content-type fail when parameters not match - regexp', async t => {
|
|
@@ -622,7 +633,7 @@ test('content-type fail when parameters not match - regexp', async t => {
|
|
|
622
633
|
const fastify = Fastify()
|
|
623
634
|
fastify.removeAllContentTypeParsers()
|
|
624
635
|
fastify.addContentTypeParser(/application\/json; charset=utf8; foo=bar/, function (request, body, done) {
|
|
625
|
-
t.fail('shouldn\'t be called')
|
|
636
|
+
t.assert.fail('shouldn\'t be called')
|
|
626
637
|
done(null, body)
|
|
627
638
|
})
|
|
628
639
|
|
|
@@ -639,7 +650,7 @@ test('content-type fail when parameters not match - regexp', async t => {
|
|
|
639
650
|
body: ''
|
|
640
651
|
})
|
|
641
652
|
|
|
642
|
-
t.
|
|
653
|
+
t.assert.strictEqual(response.statusCode, 415)
|
|
643
654
|
})
|
|
644
655
|
|
|
645
656
|
// Refs: https://github.com/fastify/fastify/issues/4495
|
|
@@ -667,9 +678,9 @@ test('content-type regexp list should be cloned when plugin override', async t =
|
|
|
667
678
|
payload: 'jpeg',
|
|
668
679
|
headers: { 'content-type': 'image/jpeg' }
|
|
669
680
|
})
|
|
670
|
-
t.
|
|
671
|
-
t.
|
|
672
|
-
t.
|
|
681
|
+
t.assert.strictEqual(statusCode, 200)
|
|
682
|
+
t.assert.strictEqual(headers['content-type'], 'image/jpeg')
|
|
683
|
+
t.assert.strictEqual(payload, 'jpeg')
|
|
673
684
|
}
|
|
674
685
|
|
|
675
686
|
{
|
|
@@ -679,9 +690,9 @@ test('content-type regexp list should be cloned when plugin override', async t =
|
|
|
679
690
|
payload: 'png',
|
|
680
691
|
headers: { 'content-type': 'image/png' }
|
|
681
692
|
})
|
|
682
|
-
t.
|
|
683
|
-
t.
|
|
684
|
-
t.
|
|
693
|
+
t.assert.strictEqual(statusCode, 200)
|
|
694
|
+
t.assert.strictEqual(headers['content-type'], 'image/png')
|
|
695
|
+
t.assert.strictEqual(payload, 'png')
|
|
685
696
|
}
|
|
686
697
|
})
|
|
687
698
|
|
|
@@ -691,7 +702,7 @@ test('edge case content-type - ;', async t => {
|
|
|
691
702
|
const fastify = Fastify()
|
|
692
703
|
fastify.removeAllContentTypeParsers()
|
|
693
704
|
fastify.addContentTypeParser(';', function (request, body, done) {
|
|
694
|
-
t.fail('should not be called')
|
|
705
|
+
t.assert.fail('should not be called')
|
|
695
706
|
done(null, body)
|
|
696
707
|
})
|
|
697
708
|
|
|
@@ -717,5 +728,5 @@ test('edge case content-type - ;', async t => {
|
|
|
717
728
|
body: ''
|
|
718
729
|
})
|
|
719
730
|
|
|
720
|
-
t.
|
|
731
|
+
t.assert.ok('end')
|
|
721
732
|
})
|