fastify 5.4.0 → 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 +22 -0
- package/LICENSE +1 -1
- package/SECURITY.md +158 -2
- package/build/build-validation.js +19 -1
- package/docs/Guides/Delay-Accepting-Requests.md +8 -5
- package/docs/Guides/Ecosystem.md +11 -0
- package/docs/Guides/Migration-Guide-V5.md +6 -10
- package/docs/Guides/Recommendations.md +1 -1
- package/docs/Reference/Errors.md +3 -1
- package/docs/Reference/Hooks.md +2 -6
- package/docs/Reference/Lifecycle.md +2 -2
- package/docs/Reference/Request.md +1 -1
- package/docs/Reference/Routes.md +4 -3
- package/docs/Reference/Server.md +306 -179
- package/docs/Reference/TypeScript.md +1 -3
- package/docs/Reference/Validation-and-Serialization.md +55 -3
- package/docs/Reference/Warnings.md +2 -1
- package/fastify.d.ts +2 -2
- package/fastify.js +34 -33
- package/lib/configValidator.js +196 -28
- package/lib/contentTypeParser.js +41 -48
- package/lib/error-handler.js +3 -3
- package/lib/errors.js +5 -0
- package/lib/handleRequest.js +13 -17
- package/lib/promise.js +23 -0
- package/lib/reply.js +17 -19
- package/lib/route.js +37 -3
- package/lib/server.js +36 -35
- package/lib/warnings.js +11 -1
- package/package.json +7 -7
- package/test/async-await.test.js +81 -134
- package/test/async_hooks.test.js +18 -37
- package/test/body-limit.test.js +51 -0
- package/test/buffer.test.js +22 -0
- 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.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.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-request.test.js +8 -16
- package/test/diagnostics-channel/error-request.test.js +7 -15
- 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 +138 -134
- package/test/hooks-async.test.js +26 -32
- package/test/hooks.test.js +261 -447
- 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/mkcalendar.test.js +45 -72
- package/test/http-methods/move.test.js +6 -10
- package/test/http-methods/propfind.test.js +34 -44
- package/test/http-methods/unlock.test.js +5 -9
- package/test/http2/secure-with-fallback.test.js +3 -1
- package/test/https/custom-https-server.test.js +9 -13
- package/test/input-validation.js +139 -150
- package/test/internals/errors.test.js +50 -1
- package/test/internals/handle-request.test.js +29 -5
- package/test/internals/promise.test.js +63 -0
- package/test/internals/reply.test.js +277 -496
- package/test/plugin.1.test.js +40 -68
- package/test/plugin.2.test.js +40 -70
- package/test/plugin.3.test.js +25 -68
- package/test/promises.test.js +42 -63
- package/test/register.test.js +8 -18
- package/test/request-error.test.js +57 -100
- package/test/request-id.test.js +30 -49
- package/test/route-hooks.test.js +12 -16
- 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-validation.test.js +30 -31
- package/test/server.test.js +143 -5
- 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/types/errors.test-d.ts +13 -1
- package/test/types/type-provider.test-d.ts +55 -0
- 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/test/input-validation.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const sget = require('simple-get').concat
|
|
4
3
|
const Ajv = require('ajv')
|
|
5
4
|
const Joi = require('joi')
|
|
6
5
|
const yup = require('yup')
|
|
@@ -139,207 +138,197 @@ module.exports.payloadMethod = function (method, t) {
|
|
|
139
138
|
|
|
140
139
|
t.after(() => { fastify.close() })
|
|
141
140
|
|
|
142
|
-
test(`${upMethod} - correctly replies`, (t
|
|
141
|
+
test(`${upMethod} - correctly replies`, async (t) => {
|
|
143
142
|
if (upMethod === 'HEAD') {
|
|
144
143
|
t.plan(2)
|
|
145
|
-
|
|
146
|
-
method: upMethod
|
|
147
|
-
url: 'http://localhost:' + fastify.server.address().port
|
|
148
|
-
}, (err, response) => {
|
|
149
|
-
t.assert.ifError(err)
|
|
150
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
151
|
-
testDone()
|
|
144
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port, {
|
|
145
|
+
method: upMethod
|
|
152
146
|
})
|
|
147
|
+
t.assert.ok(result.ok)
|
|
148
|
+
t.assert.strictEqual(result.status, 200)
|
|
153
149
|
} else {
|
|
154
150
|
t.plan(3)
|
|
155
|
-
|
|
151
|
+
|
|
152
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port, {
|
|
156
153
|
method: upMethod,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
json: true
|
|
162
|
-
}, (err, response, body) => {
|
|
163
|
-
t.assert.ifError(err)
|
|
164
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
165
|
-
t.assert.deepStrictEqual(body, { hello: 42 })
|
|
166
|
-
testDone()
|
|
154
|
+
body: JSON.stringify({ hello: 42 }),
|
|
155
|
+
headers: {
|
|
156
|
+
'Content-Type': 'application/json'
|
|
157
|
+
}
|
|
167
158
|
})
|
|
159
|
+
|
|
160
|
+
t.assert.ok(result.ok)
|
|
161
|
+
t.assert.strictEqual(result.status, 200)
|
|
162
|
+
t.assert.deepStrictEqual(await result.json(), { hello: 42 })
|
|
168
163
|
}
|
|
169
164
|
})
|
|
170
165
|
|
|
171
|
-
test(`${upMethod} - 400 on bad parameters`, (t
|
|
166
|
+
test(`${upMethod} - 400 on bad parameters`, async (t) => {
|
|
172
167
|
t.plan(3)
|
|
173
|
-
|
|
168
|
+
|
|
169
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port, {
|
|
174
170
|
method: upMethod,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
})
|
|
189
|
-
testDone()
|
|
171
|
+
body: JSON.stringify({ hello: 'world' }),
|
|
172
|
+
headers: {
|
|
173
|
+
'Content-Type': 'application/json'
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
t.assert.ok(!result.ok)
|
|
178
|
+
t.assert.strictEqual(result.status, 400)
|
|
179
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
180
|
+
error: 'Bad Request',
|
|
181
|
+
message: 'body/hello must be integer',
|
|
182
|
+
statusCode: 400,
|
|
183
|
+
code: 'FST_ERR_VALIDATION'
|
|
190
184
|
})
|
|
191
185
|
})
|
|
192
186
|
|
|
193
|
-
test(`${upMethod} - input-validation coerce`, (t
|
|
187
|
+
test(`${upMethod} - input-validation coerce`, async (t) => {
|
|
194
188
|
t.plan(3)
|
|
195
|
-
|
|
189
|
+
|
|
190
|
+
const restult = await fetch('http://localhost:' + fastify.server.address().port, {
|
|
196
191
|
method: upMethod,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
json: true
|
|
202
|
-
}, (err, response, body) => {
|
|
203
|
-
t.assert.ifError(err)
|
|
204
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
205
|
-
t.assert.deepStrictEqual(body, { hello: 42 })
|
|
206
|
-
testDone()
|
|
192
|
+
body: JSON.stringify({ hello: '42' }),
|
|
193
|
+
headers: {
|
|
194
|
+
'Content-Type': 'application/json'
|
|
195
|
+
}
|
|
207
196
|
})
|
|
197
|
+
|
|
198
|
+
t.assert.ok(restult.ok)
|
|
199
|
+
t.assert.strictEqual(restult.status, 200)
|
|
200
|
+
t.assert.deepStrictEqual(await restult.json(), { hello: 42 })
|
|
208
201
|
})
|
|
209
202
|
|
|
210
|
-
test(`${upMethod} - input-validation custom schema compiler`, (t
|
|
203
|
+
test(`${upMethod} - input-validation custom schema compiler`, async (t) => {
|
|
211
204
|
t.plan(3)
|
|
212
|
-
|
|
205
|
+
|
|
206
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/custom', {
|
|
213
207
|
method: upMethod,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
},
|
|
219
|
-
json: true
|
|
220
|
-
}, (err, response, body) => {
|
|
221
|
-
t.assert.ifError(err)
|
|
222
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
223
|
-
t.assert.deepStrictEqual(body, { hello: 42 })
|
|
224
|
-
testDone()
|
|
208
|
+
body: JSON.stringify({ hello: '42', world: 55 }),
|
|
209
|
+
headers: {
|
|
210
|
+
'Content-Type': 'application/json'
|
|
211
|
+
}
|
|
225
212
|
})
|
|
213
|
+
|
|
214
|
+
t.assert.ok(result.ok)
|
|
215
|
+
t.assert.strictEqual(result.status, 200)
|
|
216
|
+
t.assert.deepStrictEqual(await result.json(), { hello: 42 })
|
|
226
217
|
})
|
|
227
218
|
|
|
228
|
-
test(`${upMethod} - input-validation joi schema compiler ok`, (t
|
|
219
|
+
test(`${upMethod} - input-validation joi schema compiler ok`, async (t) => {
|
|
229
220
|
t.plan(3)
|
|
230
|
-
|
|
221
|
+
|
|
222
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/joi', {
|
|
231
223
|
method: upMethod,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
json: true
|
|
237
|
-
}, (err, response, body) => {
|
|
238
|
-
t.assert.ifError(err)
|
|
239
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
240
|
-
t.assert.deepStrictEqual(body, { hello: '42' })
|
|
241
|
-
testDone()
|
|
224
|
+
body: JSON.stringify({ hello: '42' }),
|
|
225
|
+
headers: {
|
|
226
|
+
'Content-Type': 'application/json'
|
|
227
|
+
}
|
|
242
228
|
})
|
|
229
|
+
|
|
230
|
+
t.assert.ok(result.ok)
|
|
231
|
+
t.assert.strictEqual(result.status, 200)
|
|
232
|
+
t.assert.deepStrictEqual(await result.json(), { hello: '42' })
|
|
243
233
|
})
|
|
244
234
|
|
|
245
|
-
test(`${upMethod} - input-validation joi schema compiler ko`, (t
|
|
235
|
+
test(`${upMethod} - input-validation joi schema compiler ko`, async (t) => {
|
|
246
236
|
t.plan(3)
|
|
247
|
-
|
|
237
|
+
|
|
238
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/joi', {
|
|
248
239
|
method: upMethod,
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
})
|
|
263
|
-
testDone()
|
|
240
|
+
body: JSON.stringify({ hello: 44 }),
|
|
241
|
+
headers: {
|
|
242
|
+
'Content-Type': 'application/json'
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
t.assert.ok(!result.ok)
|
|
247
|
+
t.assert.strictEqual(result.status, 400)
|
|
248
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
249
|
+
error: 'Bad Request',
|
|
250
|
+
message: '"hello" must be a string',
|
|
251
|
+
statusCode: 400,
|
|
252
|
+
code: 'FST_ERR_VALIDATION'
|
|
264
253
|
})
|
|
265
254
|
})
|
|
266
255
|
|
|
267
|
-
test(`${upMethod} - input-validation yup schema compiler ok`, (t
|
|
256
|
+
test(`${upMethod} - input-validation yup schema compiler ok`, async (t) => {
|
|
268
257
|
t.plan(3)
|
|
269
|
-
|
|
258
|
+
|
|
259
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/yup', {
|
|
270
260
|
method: upMethod,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
json: true
|
|
276
|
-
}, (err, response, body) => {
|
|
277
|
-
t.assert.ifError(err)
|
|
278
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
279
|
-
t.assert.deepStrictEqual(body, { hello: '42' })
|
|
280
|
-
testDone()
|
|
261
|
+
body: JSON.stringify({ hello: '42' }),
|
|
262
|
+
headers: {
|
|
263
|
+
'Content-Type': 'application/json'
|
|
264
|
+
}
|
|
281
265
|
})
|
|
266
|
+
|
|
267
|
+
t.assert.ok(result.ok)
|
|
268
|
+
t.assert.strictEqual(result.status, 200)
|
|
269
|
+
t.assert.deepStrictEqual(await result.json(), { hello: '42' })
|
|
282
270
|
})
|
|
283
271
|
|
|
284
|
-
test(`${upMethod} - input-validation yup schema compiler ko`, (t
|
|
272
|
+
test(`${upMethod} - input-validation yup schema compiler ko`, async (t) => {
|
|
285
273
|
t.plan(3)
|
|
286
|
-
|
|
274
|
+
|
|
275
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/yup', {
|
|
287
276
|
method: upMethod,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
})
|
|
302
|
-
testDone()
|
|
277
|
+
body: JSON.stringify({ hello: 44 }),
|
|
278
|
+
headers: {
|
|
279
|
+
'Content-Type': 'application/json'
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
t.assert.ok(!result.ok)
|
|
284
|
+
t.assert.strictEqual(result.status, 400)
|
|
285
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
286
|
+
error: 'Bad Request',
|
|
287
|
+
message: 'body hello must be a `string` type, but the final value was: `44`.',
|
|
288
|
+
statusCode: 400,
|
|
289
|
+
code: 'FST_ERR_VALIDATION'
|
|
303
290
|
})
|
|
304
291
|
})
|
|
305
292
|
|
|
306
|
-
test(`${upMethod} - input-validation instance custom schema compiler encapsulated`, (t
|
|
293
|
+
test(`${upMethod} - input-validation instance custom schema compiler encapsulated`, async (t) => {
|
|
307
294
|
t.plan(3)
|
|
308
|
-
|
|
295
|
+
|
|
296
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/plugin', {
|
|
309
297
|
method: upMethod,
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
298
|
+
body: JSON.stringify({}),
|
|
299
|
+
headers: {
|
|
300
|
+
'Content-Type': 'application/json'
|
|
301
|
+
}
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
t.assert.ok(!result.ok)
|
|
305
|
+
t.assert.strictEqual(result.status, 400)
|
|
306
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
307
|
+
error: 'Bad Request',
|
|
308
|
+
message: 'From custom schema compiler!',
|
|
309
|
+
statusCode: 400,
|
|
310
|
+
code: 'FST_ERR_VALIDATION'
|
|
323
311
|
})
|
|
324
312
|
})
|
|
325
313
|
|
|
326
|
-
test(`${upMethod} - input-validation custom schema compiler encapsulated`, (t
|
|
314
|
+
test(`${upMethod} - input-validation custom schema compiler encapsulated`, async (t) => {
|
|
327
315
|
t.plan(3)
|
|
328
|
-
|
|
316
|
+
|
|
317
|
+
const result = await fetch('http://localhost:' + fastify.server.address().port + '/plugin/custom', {
|
|
329
318
|
method: upMethod,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
319
|
+
body: JSON.stringify({}),
|
|
320
|
+
headers: {
|
|
321
|
+
'Content-Type': 'application/json'
|
|
322
|
+
}
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
t.assert.ok(!result.ok)
|
|
326
|
+
t.assert.strictEqual(result.status, 400)
|
|
327
|
+
t.assert.deepStrictEqual(await result.json(), {
|
|
328
|
+
error: 'Bad Request',
|
|
329
|
+
message: 'Always fail!',
|
|
330
|
+
statusCode: 400,
|
|
331
|
+
code: 'FST_ERR_VALIDATION'
|
|
343
332
|
})
|
|
344
333
|
})
|
|
345
334
|
})
|
|
@@ -5,7 +5,7 @@ const errors = require('../../lib/errors')
|
|
|
5
5
|
const { readFileSync } = require('node:fs')
|
|
6
6
|
const { resolve } = require('node:path')
|
|
7
7
|
|
|
8
|
-
const expectedErrors =
|
|
8
|
+
const expectedErrors = 86
|
|
9
9
|
|
|
10
10
|
test(`should expose ${expectedErrors} errors`, t => {
|
|
11
11
|
t.plan(1)
|
|
@@ -190,6 +190,16 @@ test('FST_ERR_CTP_EMPTY_JSON_BODY', t => {
|
|
|
190
190
|
t.assert.ok(error instanceof Error)
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
+
test('FST_ERR_CTP_INVALID_JSON_BODY', t => {
|
|
194
|
+
t.plan(5)
|
|
195
|
+
const error = new errors.FST_ERR_CTP_INVALID_JSON_BODY()
|
|
196
|
+
t.assert.strictEqual(error.name, 'FastifyError')
|
|
197
|
+
t.assert.strictEqual(error.code, 'FST_ERR_CTP_INVALID_JSON_BODY')
|
|
198
|
+
t.assert.strictEqual(error.message, "Body is not valid JSON but content-type is set to 'application/json'")
|
|
199
|
+
t.assert.strictEqual(error.statusCode, 400)
|
|
200
|
+
t.assert.ok(error instanceof Error)
|
|
201
|
+
})
|
|
202
|
+
|
|
193
203
|
test('FST_ERR_CTP_INSTANCE_ALREADY_STARTED', t => {
|
|
194
204
|
t.plan(5)
|
|
195
205
|
const error = new errors.FST_ERR_CTP_INSTANCE_ALREADY_STARTED()
|
|
@@ -931,3 +941,42 @@ test('Ensure that non-existing errors are not in Errors.md documented', t => {
|
|
|
931
941
|
t.assert.ok(exportedKeys.indexOf(match[1]) !== -1, match[1])
|
|
932
942
|
}
|
|
933
943
|
})
|
|
944
|
+
|
|
945
|
+
test('Ensure that all errors are in errors.d.ts', t => {
|
|
946
|
+
t.plan(expectedErrors)
|
|
947
|
+
|
|
948
|
+
const errorsDts = readFileSync(resolve(__dirname, '../../types/errors.d.ts'), 'utf8')
|
|
949
|
+
|
|
950
|
+
const FastifyErrorCodesRE = /export type FastifyErrorCodes = Record<([^>]+),\s*FastifyErrorConstructor>/m
|
|
951
|
+
|
|
952
|
+
const [, errorCodeType] = errorsDts.match(FastifyErrorCodesRE)
|
|
953
|
+
|
|
954
|
+
const errorCodeRE = /'([A-Z0-9_]+)'/g
|
|
955
|
+
const matches = errorCodeType.matchAll(errorCodeRE)
|
|
956
|
+
const errorTypes = [...matches].map(match => match[1])
|
|
957
|
+
const exportedKeys = Object.keys(errors)
|
|
958
|
+
|
|
959
|
+
for (const key of exportedKeys) {
|
|
960
|
+
if (errors[key].name === 'FastifyError') {
|
|
961
|
+
t.assert.ok(errorTypes.includes(key), key)
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
})
|
|
965
|
+
|
|
966
|
+
test('Ensure that non-existing errors are not in errors.d.ts', t => {
|
|
967
|
+
t.plan(expectedErrors)
|
|
968
|
+
|
|
969
|
+
const errorsDts = readFileSync(resolve(__dirname, '../../types/errors.d.ts'), 'utf8')
|
|
970
|
+
|
|
971
|
+
const FastifyErrorCodesRE = /export type FastifyErrorCodes = Record<([^>]+),\s*FastifyErrorConstructor>/m
|
|
972
|
+
|
|
973
|
+
const [, errorCodeType] = errorsDts.match(FastifyErrorCodesRE)
|
|
974
|
+
|
|
975
|
+
const errorCodeRE = /'([A-Z0-9_]+)'/g
|
|
976
|
+
const matches = errorCodeType.matchAll(errorCodeRE)
|
|
977
|
+
const exportedKeys = Object.keys(errors)
|
|
978
|
+
|
|
979
|
+
for (const match of matches) {
|
|
980
|
+
t.assert.ok(exportedKeys.indexOf(match[1]) !== -1, match[1])
|
|
981
|
+
}
|
|
982
|
+
})
|
|
@@ -191,7 +191,7 @@ test('request should be defined in onSend Hook on post request with content type
|
|
|
191
191
|
})
|
|
192
192
|
|
|
193
193
|
test('request should be defined in onSend Hook on options request with content type application/x-www-form-urlencoded', async t => {
|
|
194
|
-
t.plan(
|
|
194
|
+
t.plan(15)
|
|
195
195
|
const fastify = require('../..')()
|
|
196
196
|
|
|
197
197
|
t.after(() => {
|
|
@@ -209,16 +209,40 @@ test('request should be defined in onSend Hook on options request with content t
|
|
|
209
209
|
reply.send(200)
|
|
210
210
|
})
|
|
211
211
|
|
|
212
|
-
|
|
213
|
-
const
|
|
212
|
+
// Test 1: OPTIONS with body and content-type header
|
|
213
|
+
const result1 = await fastify.inject({
|
|
214
|
+
method: 'OPTIONS',
|
|
215
|
+
url: '/',
|
|
216
|
+
body: 'first-name=OPTIONS&last-name=METHOD',
|
|
217
|
+
headers: {
|
|
218
|
+
'content-type': 'application/x-www-form-urlencoded'
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
// Content-Type is not supported
|
|
223
|
+
t.assert.strictEqual(result1.statusCode, 415)
|
|
224
|
+
|
|
225
|
+
// Test 2: OPTIONS with content-type header only (no body)
|
|
226
|
+
const result2 = await fastify.inject({
|
|
214
227
|
method: 'OPTIONS',
|
|
228
|
+
url: '/',
|
|
215
229
|
headers: {
|
|
216
230
|
'content-type': 'application/x-www-form-urlencoded'
|
|
217
231
|
}
|
|
218
232
|
})
|
|
219
233
|
|
|
220
|
-
//
|
|
221
|
-
t.assert.strictEqual(
|
|
234
|
+
// Content-Type is not supported
|
|
235
|
+
t.assert.strictEqual(result2.statusCode, 415)
|
|
236
|
+
|
|
237
|
+
// Test 3: OPTIONS with body but no content-type header
|
|
238
|
+
const result3 = await fastify.inject({
|
|
239
|
+
method: 'OPTIONS',
|
|
240
|
+
url: '/',
|
|
241
|
+
body: 'first-name=OPTIONS&last-name=METHOD'
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
// No content-type with payload
|
|
245
|
+
t.assert.strictEqual(result3.statusCode, 415)
|
|
222
246
|
})
|
|
223
247
|
|
|
224
248
|
test('request should respond with an error if an unserialized payload is sent inside an async handler', async t => {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
|
|
5
|
+
const { kTestInternals } = require('../../lib/symbols')
|
|
6
|
+
const PonyPromise = require('../../lib/promise')
|
|
7
|
+
|
|
8
|
+
test('withResolvers', async (t) => {
|
|
9
|
+
t.plan(3)
|
|
10
|
+
await t.test('resolve', async (t) => {
|
|
11
|
+
t.plan(1)
|
|
12
|
+
const { promise, resolve } = PonyPromise.withResolvers()
|
|
13
|
+
resolve(true)
|
|
14
|
+
t.assert.ok(await promise)
|
|
15
|
+
})
|
|
16
|
+
await t.test('reject', async (t) => {
|
|
17
|
+
t.plan(1)
|
|
18
|
+
const { promise, reject } = PonyPromise.withResolvers()
|
|
19
|
+
await t.assert.rejects(async () => {
|
|
20
|
+
reject(Error('reject'))
|
|
21
|
+
return promise
|
|
22
|
+
}, {
|
|
23
|
+
name: 'Error',
|
|
24
|
+
message: 'reject'
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
await t.test('thenable', async (t) => {
|
|
28
|
+
t.plan(1)
|
|
29
|
+
const { promise, resolve } = PonyPromise.withResolvers()
|
|
30
|
+
resolve(true)
|
|
31
|
+
promise.then((value) => {
|
|
32
|
+
t.assert.ok(value)
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('withResolvers - ponyfill', async (t) => {
|
|
38
|
+
await t.test('resolve', async (t) => {
|
|
39
|
+
t.plan(1)
|
|
40
|
+
const { promise, resolve } = PonyPromise[kTestInternals].withResolvers()
|
|
41
|
+
resolve(true)
|
|
42
|
+
t.assert.ok(await promise)
|
|
43
|
+
})
|
|
44
|
+
await t.test('reject', async (t) => {
|
|
45
|
+
t.plan(1)
|
|
46
|
+
const { promise, reject } = PonyPromise[kTestInternals].withResolvers()
|
|
47
|
+
await t.assert.rejects(async () => {
|
|
48
|
+
reject(Error('reject'))
|
|
49
|
+
return promise
|
|
50
|
+
}, {
|
|
51
|
+
name: 'Error',
|
|
52
|
+
message: 'reject'
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
await t.test('thenable', async (t) => {
|
|
56
|
+
t.plan(1)
|
|
57
|
+
const { promise, resolve } = PonyPromise.withResolvers()
|
|
58
|
+
resolve(true)
|
|
59
|
+
promise.then((value) => {
|
|
60
|
+
t.assert.ok(value)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
})
|