fastify 5.3.0 → 5.3.2
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/docs/Guides/Benchmarking.md +1 -1
- package/fastify.js +1 -1
- package/lib/validation.js +11 -1
- package/package.json +1 -1
- package/test/custom-parser.0.test.js +160 -129
- package/test/custom-parser.1.test.js +77 -63
- package/test/custom-querystring-parser.test.js +46 -28
- package/test/logger/instantiation.test.js +89 -96
- package/test/logger/logging.test.js +116 -120
- package/test/logger/options.test.js +97 -99
- package/test/logger/request.test.js +66 -66
- package/test/schema-validation.test.js +136 -0
- package/test/stream.4.test.js +38 -33
- package/test/toolkit.js +31 -0
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
const stream = require('node:stream')
|
|
4
4
|
|
|
5
|
-
const t = require('
|
|
5
|
+
const t = require('node:test')
|
|
6
6
|
const split = require('split2')
|
|
7
7
|
|
|
8
8
|
const Fastify = require('../../fastify')
|
|
9
9
|
const helper = require('../helper')
|
|
10
10
|
const { on } = stream
|
|
11
11
|
const { request } = require('./logger-test-utils')
|
|
12
|
+
const { partialDeepStrictEqual } = require('../toolkit')
|
|
12
13
|
|
|
13
|
-
t.test('request', (t) => {
|
|
14
|
-
t.setTimeout(60000)
|
|
15
|
-
|
|
14
|
+
t.test('request', { timeout: 60000 }, async (t) => {
|
|
16
15
|
let localhost
|
|
17
16
|
|
|
18
17
|
t.plan(7)
|
|
@@ -20,7 +19,7 @@ t.test('request', (t) => {
|
|
|
20
19
|
[localhost] = await helper.getLoopbackHost()
|
|
21
20
|
})
|
|
22
21
|
|
|
23
|
-
t.test('The request id header key can be customized', async (t) => {
|
|
22
|
+
await t.test('The request id header key can be customized', async (t) => {
|
|
24
23
|
const lines = ['incoming request', 'some log message', 'request completed']
|
|
25
24
|
t.plan(lines.length * 2 + 2)
|
|
26
25
|
const REQUEST_ID = '42'
|
|
@@ -30,26 +29,26 @@ t.test('request', (t) => {
|
|
|
30
29
|
logger: { stream, level: 'info' },
|
|
31
30
|
requestIdHeader: 'my-custom-request-id'
|
|
32
31
|
})
|
|
33
|
-
t.
|
|
32
|
+
t.after(() => fastify.close())
|
|
34
33
|
|
|
35
34
|
fastify.get('/', (req, reply) => {
|
|
36
|
-
t.
|
|
35
|
+
t.assert.strictEqual(req.id, REQUEST_ID)
|
|
37
36
|
req.log.info('some log message')
|
|
38
37
|
reply.send({ id: req.id })
|
|
39
38
|
})
|
|
40
39
|
|
|
41
40
|
const response = await fastify.inject({ method: 'GET', url: '/', headers: { 'my-custom-request-id': REQUEST_ID } })
|
|
42
41
|
const body = await response.json()
|
|
43
|
-
t.
|
|
42
|
+
t.assert.strictEqual(body.id, REQUEST_ID)
|
|
44
43
|
|
|
45
44
|
for await (const [line] of on(stream, 'data')) {
|
|
46
|
-
t.
|
|
47
|
-
t.
|
|
45
|
+
t.assert.strictEqual(line.reqId, REQUEST_ID)
|
|
46
|
+
t.assert.strictEqual(line.msg, lines.shift(), 'message is set')
|
|
48
47
|
if (lines.length === 0) break
|
|
49
48
|
}
|
|
50
49
|
})
|
|
51
50
|
|
|
52
|
-
t.test('The request id header key can be ignored', async (t) => {
|
|
51
|
+
await t.test('The request id header key can be ignored', async (t) => {
|
|
53
52
|
const lines = ['incoming request', 'some log message', 'request completed']
|
|
54
53
|
t.plan(lines.length * 2 + 2)
|
|
55
54
|
const REQUEST_ID = 'ignore-me'
|
|
@@ -59,33 +58,33 @@ t.test('request', (t) => {
|
|
|
59
58
|
logger: { stream, level: 'info' },
|
|
60
59
|
requestIdHeader: false
|
|
61
60
|
})
|
|
62
|
-
t.
|
|
61
|
+
t.after(() => fastify.close())
|
|
63
62
|
|
|
64
63
|
fastify.get('/', (req, reply) => {
|
|
65
|
-
t.
|
|
64
|
+
t.assert.strictEqual(req.id, 'req-1')
|
|
66
65
|
req.log.info('some log message')
|
|
67
66
|
reply.send({ id: req.id })
|
|
68
67
|
})
|
|
69
68
|
const response = await fastify.inject({ method: 'GET', url: '/', headers: { 'request-id': REQUEST_ID } })
|
|
70
69
|
const body = await response.json()
|
|
71
|
-
t.
|
|
70
|
+
t.assert.strictEqual(body.id, 'req-1')
|
|
72
71
|
|
|
73
72
|
for await (const [line] of on(stream, 'data')) {
|
|
74
|
-
t.
|
|
75
|
-
t.
|
|
73
|
+
t.assert.strictEqual(line.reqId, 'req-1')
|
|
74
|
+
t.assert.strictEqual(line.msg, lines.shift(), 'message is set')
|
|
76
75
|
if (lines.length === 0) break
|
|
77
76
|
}
|
|
78
77
|
})
|
|
79
78
|
|
|
80
|
-
t.test('The request id header key can be customized along with a custom id generator', async (t) => {
|
|
79
|
+
await t.test('The request id header key can be customized along with a custom id generator', async (t) => {
|
|
81
80
|
const REQUEST_ID = '42'
|
|
82
81
|
const matches = [
|
|
83
|
-
{ reqId: REQUEST_ID, msg:
|
|
84
|
-
{ reqId: REQUEST_ID, msg:
|
|
85
|
-
{ reqId: REQUEST_ID, msg:
|
|
86
|
-
{ reqId: 'foo', msg:
|
|
87
|
-
{ reqId: 'foo', msg:
|
|
88
|
-
{ reqId: 'foo', msg:
|
|
82
|
+
{ reqId: REQUEST_ID, msg: 'incoming request' },
|
|
83
|
+
{ reqId: REQUEST_ID, msg: 'some log message' },
|
|
84
|
+
{ reqId: REQUEST_ID, msg: 'request completed' },
|
|
85
|
+
{ reqId: 'foo', msg: 'incoming request' },
|
|
86
|
+
{ reqId: 'foo', msg: 'some log message 2' },
|
|
87
|
+
{ reqId: 'foo', msg: 'request completed' }
|
|
89
88
|
]
|
|
90
89
|
t.plan(matches.length + 4)
|
|
91
90
|
|
|
@@ -97,16 +96,16 @@ t.test('request', (t) => {
|
|
|
97
96
|
return 'foo'
|
|
98
97
|
}
|
|
99
98
|
})
|
|
100
|
-
t.
|
|
99
|
+
t.after(() => fastify.close())
|
|
101
100
|
|
|
102
101
|
fastify.get('/one', (req, reply) => {
|
|
103
|
-
t.
|
|
102
|
+
t.assert.strictEqual(req.id, REQUEST_ID)
|
|
104
103
|
req.log.info('some log message')
|
|
105
104
|
reply.send({ id: req.id })
|
|
106
105
|
})
|
|
107
106
|
|
|
108
107
|
fastify.get('/two', (req, reply) => {
|
|
109
|
-
t.
|
|
108
|
+
t.assert.strictEqual(req.id, 'foo')
|
|
110
109
|
req.log.info('some log message 2')
|
|
111
110
|
reply.send({ id: req.id })
|
|
112
111
|
})
|
|
@@ -114,30 +113,30 @@ t.test('request', (t) => {
|
|
|
114
113
|
{
|
|
115
114
|
const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'my-custom-request-id': REQUEST_ID } })
|
|
116
115
|
const body = await response.json()
|
|
117
|
-
t.
|
|
116
|
+
t.assert.strictEqual(body.id, REQUEST_ID)
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
{
|
|
121
120
|
const response = await fastify.inject({ method: 'GET', url: '/two' })
|
|
122
121
|
const body = await response.json()
|
|
123
|
-
t.
|
|
122
|
+
t.assert.strictEqual(body.id, 'foo')
|
|
124
123
|
}
|
|
125
124
|
|
|
126
125
|
for await (const [line] of on(stream, 'data')) {
|
|
127
|
-
t.
|
|
126
|
+
t.assert.ok(partialDeepStrictEqual(line, matches.shift()))
|
|
128
127
|
if (matches.length === 0) break
|
|
129
128
|
}
|
|
130
129
|
})
|
|
131
130
|
|
|
132
|
-
t.test('The request id header key can be ignored along with a custom id generator', async (t) => {
|
|
131
|
+
await t.test('The request id header key can be ignored along with a custom id generator', async (t) => {
|
|
133
132
|
const REQUEST_ID = 'ignore-me'
|
|
134
133
|
const matches = [
|
|
135
|
-
{ reqId: 'foo', msg:
|
|
136
|
-
{ reqId: 'foo', msg:
|
|
137
|
-
{ reqId: 'foo', msg:
|
|
138
|
-
{ reqId: 'foo', msg:
|
|
139
|
-
{ reqId: 'foo', msg:
|
|
140
|
-
{ reqId: 'foo', msg:
|
|
134
|
+
{ reqId: 'foo', msg: 'incoming request' },
|
|
135
|
+
{ reqId: 'foo', msg: 'some log message' },
|
|
136
|
+
{ reqId: 'foo', msg: 'request completed' },
|
|
137
|
+
{ reqId: 'foo', msg: 'incoming request' },
|
|
138
|
+
{ reqId: 'foo', msg: 'some log message 2' },
|
|
139
|
+
{ reqId: 'foo', msg: 'request completed' }
|
|
141
140
|
]
|
|
142
141
|
t.plan(matches.length + 4)
|
|
143
142
|
|
|
@@ -149,16 +148,16 @@ t.test('request', (t) => {
|
|
|
149
148
|
return 'foo'
|
|
150
149
|
}
|
|
151
150
|
})
|
|
152
|
-
t.
|
|
151
|
+
t.after(() => fastify.close())
|
|
153
152
|
|
|
154
153
|
fastify.get('/one', (req, reply) => {
|
|
155
|
-
t.
|
|
154
|
+
t.assert.strictEqual(req.id, 'foo')
|
|
156
155
|
req.log.info('some log message')
|
|
157
156
|
reply.send({ id: req.id })
|
|
158
157
|
})
|
|
159
158
|
|
|
160
159
|
fastify.get('/two', (req, reply) => {
|
|
161
|
-
t.
|
|
160
|
+
t.assert.strictEqual(req.id, 'foo')
|
|
162
161
|
req.log.info('some log message 2')
|
|
163
162
|
reply.send({ id: req.id })
|
|
164
163
|
})
|
|
@@ -166,27 +165,27 @@ t.test('request', (t) => {
|
|
|
166
165
|
{
|
|
167
166
|
const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'request-id': REQUEST_ID } })
|
|
168
167
|
const body = await response.json()
|
|
169
|
-
t.
|
|
168
|
+
t.assert.strictEqual(body.id, 'foo')
|
|
170
169
|
}
|
|
171
170
|
|
|
172
171
|
{
|
|
173
172
|
const response = await fastify.inject({ method: 'GET', url: '/two' })
|
|
174
173
|
const body = await response.json()
|
|
175
|
-
t.
|
|
174
|
+
t.assert.strictEqual(body.id, 'foo')
|
|
176
175
|
}
|
|
177
176
|
|
|
178
177
|
for await (const [line] of on(stream, 'data')) {
|
|
179
|
-
t.
|
|
178
|
+
t.assert.ok(partialDeepStrictEqual(line, matches.shift()))
|
|
180
179
|
if (matches.length === 0) break
|
|
181
180
|
}
|
|
182
181
|
})
|
|
183
182
|
|
|
184
|
-
t.test('The request id log label can be changed', async (t) => {
|
|
183
|
+
await t.test('The request id log label can be changed', async (t) => {
|
|
185
184
|
const REQUEST_ID = '42'
|
|
186
185
|
const matches = [
|
|
187
|
-
{ traceId: REQUEST_ID, msg:
|
|
188
|
-
{ traceId: REQUEST_ID, msg:
|
|
189
|
-
{ traceId: REQUEST_ID, msg:
|
|
186
|
+
{ traceId: REQUEST_ID, msg: 'incoming request' },
|
|
187
|
+
{ traceId: REQUEST_ID, msg: 'some log message' },
|
|
188
|
+
{ traceId: REQUEST_ID, msg: 'request completed' }
|
|
190
189
|
]
|
|
191
190
|
t.plan(matches.length + 2)
|
|
192
191
|
|
|
@@ -196,10 +195,10 @@ t.test('request', (t) => {
|
|
|
196
195
|
requestIdHeader: 'my-custom-request-id',
|
|
197
196
|
requestIdLogLabel: 'traceId'
|
|
198
197
|
})
|
|
199
|
-
t.
|
|
198
|
+
t.after(() => fastify.close())
|
|
200
199
|
|
|
201
200
|
fastify.get('/one', (req, reply) => {
|
|
202
|
-
t.
|
|
201
|
+
t.assert.strictEqual(req.id, REQUEST_ID)
|
|
203
202
|
req.log.info('some log message')
|
|
204
203
|
reply.send({ id: req.id })
|
|
205
204
|
})
|
|
@@ -207,22 +206,16 @@ t.test('request', (t) => {
|
|
|
207
206
|
{
|
|
208
207
|
const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'my-custom-request-id': REQUEST_ID } })
|
|
209
208
|
const body = await response.json()
|
|
210
|
-
t.
|
|
209
|
+
t.assert.strictEqual(body.id, REQUEST_ID)
|
|
211
210
|
}
|
|
212
211
|
|
|
213
212
|
for await (const [line] of on(stream, 'data')) {
|
|
214
|
-
t.
|
|
213
|
+
t.assert.ok(partialDeepStrictEqual(line, matches.shift()))
|
|
215
214
|
if (matches.length === 0) break
|
|
216
215
|
}
|
|
217
216
|
})
|
|
218
217
|
|
|
219
|
-
t.test('should redact the authorization header if so specified', async (t) => {
|
|
220
|
-
const lines = [
|
|
221
|
-
{ msg: /Server listening at/ },
|
|
222
|
-
{ req: { headers: { authorization: '[Redacted]' } }, msg: 'incoming request' },
|
|
223
|
-
{ res: { statusCode: 200 }, msg: 'request completed' }
|
|
224
|
-
]
|
|
225
|
-
t.plan(lines.length + 3)
|
|
218
|
+
await t.test('should redact the authorization header if so specified', async (t) => {
|
|
226
219
|
const stream = split(JSON.parse)
|
|
227
220
|
const fastify = Fastify({
|
|
228
221
|
logger: {
|
|
@@ -243,15 +236,22 @@ t.test('request', (t) => {
|
|
|
243
236
|
}
|
|
244
237
|
}
|
|
245
238
|
})
|
|
246
|
-
t.
|
|
239
|
+
t.after(() => fastify.close())
|
|
247
240
|
|
|
248
241
|
fastify.get('/', function (req, reply) {
|
|
249
|
-
t.
|
|
242
|
+
t.assert.deepStrictEqual(req.headers.authorization, 'Bearer abcde')
|
|
250
243
|
reply.send({ hello: 'world' })
|
|
251
244
|
})
|
|
252
245
|
|
|
253
246
|
await fastify.ready()
|
|
254
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
247
|
+
const server = await fastify.listen({ port: 0, host: localhost })
|
|
248
|
+
|
|
249
|
+
const lines = [
|
|
250
|
+
{ msg: `Server listening at ${server}` },
|
|
251
|
+
{ req: { headers: { authorization: '[Redacted]' } }, msg: 'incoming request' },
|
|
252
|
+
{ res: { statusCode: 200 }, msg: 'request completed' }
|
|
253
|
+
]
|
|
254
|
+
t.plan(lines.length + 3)
|
|
255
255
|
|
|
256
256
|
await request({
|
|
257
257
|
method: 'GET',
|
|
@@ -262,17 +262,17 @@ t.test('request', (t) => {
|
|
|
262
262
|
authorization: 'Bearer abcde'
|
|
263
263
|
}
|
|
264
264
|
}, function (response, body) {
|
|
265
|
-
t.
|
|
266
|
-
t.
|
|
265
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
266
|
+
t.assert.deepStrictEqual(body, JSON.stringify({ hello: 'world' }))
|
|
267
267
|
})
|
|
268
268
|
|
|
269
269
|
for await (const [line] of on(stream, 'data')) {
|
|
270
|
-
t.
|
|
270
|
+
t.assert.ok(partialDeepStrictEqual(line, lines.shift()))
|
|
271
271
|
if (lines.length === 0) break
|
|
272
272
|
}
|
|
273
273
|
})
|
|
274
274
|
|
|
275
|
-
t.test('should not throw error when serializing custom req', (t) => {
|
|
275
|
+
await t.test('should not throw error when serializing custom req', (t) => {
|
|
276
276
|
t.plan(1)
|
|
277
277
|
|
|
278
278
|
const lines = []
|
|
@@ -283,10 +283,10 @@ t.test('request', (t) => {
|
|
|
283
283
|
}
|
|
284
284
|
})
|
|
285
285
|
const fastify = Fastify({ logger: { level: 'info', stream: dest } })
|
|
286
|
-
t.
|
|
286
|
+
t.after(() => fastify.close())
|
|
287
287
|
|
|
288
288
|
fastify.log.info({ req: {} })
|
|
289
289
|
|
|
290
|
-
t.
|
|
290
|
+
t.assert.deepStrictEqual(lines[0].req, {})
|
|
291
291
|
})
|
|
292
292
|
})
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const Fastify = require('..')
|
|
5
|
+
const { request } = require('undici')
|
|
5
6
|
|
|
6
7
|
const AJV = require('ajv')
|
|
7
8
|
const Schema = require('fluent-json-schema')
|
|
@@ -1300,3 +1301,138 @@ test('Custom validator builder override by custom validator compiler in child in
|
|
|
1300
1301
|
})
|
|
1301
1302
|
t.equal(two.statusCode, 200)
|
|
1302
1303
|
})
|
|
1304
|
+
|
|
1305
|
+
test('Schema validation when no content type is provided', async t => {
|
|
1306
|
+
// this case should not be happened in normal use-case,
|
|
1307
|
+
// it is added for the completeness of code branch
|
|
1308
|
+
const fastify = Fastify()
|
|
1309
|
+
|
|
1310
|
+
fastify.post('/', {
|
|
1311
|
+
schema: {
|
|
1312
|
+
body: {
|
|
1313
|
+
content: {
|
|
1314
|
+
'application/json': {
|
|
1315
|
+
schema: {
|
|
1316
|
+
type: 'object',
|
|
1317
|
+
properties: {
|
|
1318
|
+
foo: { type: 'string' }
|
|
1319
|
+
},
|
|
1320
|
+
required: ['foo'],
|
|
1321
|
+
additionalProperties: false
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
},
|
|
1327
|
+
preValidation: async (request) => {
|
|
1328
|
+
request.headers['content-type'] = undefined
|
|
1329
|
+
}
|
|
1330
|
+
}, async () => 'ok')
|
|
1331
|
+
|
|
1332
|
+
await fastify.ready()
|
|
1333
|
+
|
|
1334
|
+
const invalid = await fastify.inject({
|
|
1335
|
+
method: 'POST',
|
|
1336
|
+
url: '/',
|
|
1337
|
+
headers: {
|
|
1338
|
+
'content-type': 'application/json'
|
|
1339
|
+
},
|
|
1340
|
+
body: { invalid: 'string' }
|
|
1341
|
+
})
|
|
1342
|
+
t.equal(invalid.statusCode, 200)
|
|
1343
|
+
})
|
|
1344
|
+
|
|
1345
|
+
test('Schema validation will not be bypass by different content type', async t => {
|
|
1346
|
+
t.plan(10)
|
|
1347
|
+
|
|
1348
|
+
const fastify = Fastify()
|
|
1349
|
+
|
|
1350
|
+
fastify.post('/', {
|
|
1351
|
+
schema: {
|
|
1352
|
+
body: {
|
|
1353
|
+
content: {
|
|
1354
|
+
'application/json': {
|
|
1355
|
+
schema: {
|
|
1356
|
+
type: 'object',
|
|
1357
|
+
properties: {
|
|
1358
|
+
foo: { type: 'string' }
|
|
1359
|
+
},
|
|
1360
|
+
required: ['foo'],
|
|
1361
|
+
additionalProperties: false
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}, async () => 'ok')
|
|
1368
|
+
|
|
1369
|
+
await fastify.listen({ port: 0 })
|
|
1370
|
+
t.teardown(() => fastify.close())
|
|
1371
|
+
const address = fastify.listeningOrigin
|
|
1372
|
+
|
|
1373
|
+
const correct1 = await request(address, {
|
|
1374
|
+
method: 'POST',
|
|
1375
|
+
url: '/',
|
|
1376
|
+
headers: {
|
|
1377
|
+
'content-type': 'application/json'
|
|
1378
|
+
},
|
|
1379
|
+
body: JSON.stringify({ foo: 'string' })
|
|
1380
|
+
})
|
|
1381
|
+
t.equal(correct1.statusCode, 200)
|
|
1382
|
+
await correct1.body.dump()
|
|
1383
|
+
|
|
1384
|
+
const correct2 = await request(address, {
|
|
1385
|
+
method: 'POST',
|
|
1386
|
+
url: '/',
|
|
1387
|
+
headers: {
|
|
1388
|
+
'content-type': 'application/json; charset=utf-8'
|
|
1389
|
+
},
|
|
1390
|
+
body: JSON.stringify({ foo: 'string' })
|
|
1391
|
+
})
|
|
1392
|
+
t.equal(correct2.statusCode, 200)
|
|
1393
|
+
await correct2.body.dump()
|
|
1394
|
+
|
|
1395
|
+
const invalid1 = await request(address, {
|
|
1396
|
+
method: 'POST',
|
|
1397
|
+
url: '/',
|
|
1398
|
+
headers: {
|
|
1399
|
+
'content-type': 'application/json ;'
|
|
1400
|
+
},
|
|
1401
|
+
body: JSON.stringify({ invalid: 'string' })
|
|
1402
|
+
})
|
|
1403
|
+
t.equal(invalid1.statusCode, 400)
|
|
1404
|
+
t.equal((await invalid1.body.json()).code, 'FST_ERR_VALIDATION')
|
|
1405
|
+
|
|
1406
|
+
const invalid2 = await request(address, {
|
|
1407
|
+
method: 'POST',
|
|
1408
|
+
url: '/',
|
|
1409
|
+
headers: {
|
|
1410
|
+
'content-type': 'ApPlIcAtIoN/JsOn;'
|
|
1411
|
+
},
|
|
1412
|
+
body: JSON.stringify({ invalid: 'string' })
|
|
1413
|
+
})
|
|
1414
|
+
t.equal(invalid2.statusCode, 400)
|
|
1415
|
+
t.equal((await invalid2.body.json()).code, 'FST_ERR_VALIDATION')
|
|
1416
|
+
|
|
1417
|
+
const invalid3 = await request(address, {
|
|
1418
|
+
method: 'POST',
|
|
1419
|
+
url: '/',
|
|
1420
|
+
headers: {
|
|
1421
|
+
'content-type': 'ApPlIcAtIoN/JsOn ;'
|
|
1422
|
+
},
|
|
1423
|
+
body: JSON.stringify({ invalid: 'string' })
|
|
1424
|
+
})
|
|
1425
|
+
t.equal(invalid3.statusCode, 400)
|
|
1426
|
+
t.equal((await invalid3.body.json()).code, 'FST_ERR_VALIDATION')
|
|
1427
|
+
|
|
1428
|
+
const invalid4 = await request(address, {
|
|
1429
|
+
method: 'POST',
|
|
1430
|
+
url: '/',
|
|
1431
|
+
headers: {
|
|
1432
|
+
'content-type': 'ApPlIcAtIoN/JsOn foo;'
|
|
1433
|
+
},
|
|
1434
|
+
body: JSON.stringify({ invalid: 'string' })
|
|
1435
|
+
})
|
|
1436
|
+
t.equal(invalid4.statusCode, 400)
|
|
1437
|
+
t.equal((await invalid4.body.json()).code, 'FST_ERR_VALIDATION')
|
|
1438
|
+
})
|
package/test/stream.4.test.js
CHANGED
|
@@ -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 sget = require('simple-get').concat
|
|
6
5
|
const errors = require('http-errors')
|
|
7
6
|
const JSONStream = require('JSONStream')
|
|
@@ -10,7 +9,7 @@ const split = require('split2')
|
|
|
10
9
|
const Fastify = require('..')
|
|
11
10
|
const { kDisableRequestLogging } = require('../lib/symbols.js')
|
|
12
11
|
|
|
13
|
-
test('Destroying streams prematurely should call abort method', t => {
|
|
12
|
+
test('Destroying streams prematurely should call abort method', (t, testDone) => {
|
|
14
13
|
t.plan(7)
|
|
15
14
|
|
|
16
15
|
let fastify = null
|
|
@@ -23,7 +22,7 @@ test('Destroying streams prematurely should call abort method', t => {
|
|
|
23
22
|
}
|
|
24
23
|
})
|
|
25
24
|
} catch (e) {
|
|
26
|
-
t.fail()
|
|
25
|
+
t.assert.fail()
|
|
27
26
|
}
|
|
28
27
|
const stream = require('node:stream')
|
|
29
28
|
const http = require('node:http')
|
|
@@ -31,13 +30,14 @@ test('Destroying streams prematurely should call abort method', t => {
|
|
|
31
30
|
// Test that "premature close" errors are logged with level warn
|
|
32
31
|
logStream.on('data', line => {
|
|
33
32
|
if (line.res) {
|
|
34
|
-
t.
|
|
35
|
-
t.
|
|
33
|
+
t.assert.strictEqual(line.msg, 'stream closed prematurely')
|
|
34
|
+
t.assert.strictEqual(line.level, 30)
|
|
35
|
+
testDone()
|
|
36
36
|
}
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
fastify.get('/', function (request, reply) {
|
|
40
|
-
t.
|
|
40
|
+
t.assert.ok('Received request')
|
|
41
41
|
|
|
42
42
|
let sent = false
|
|
43
43
|
const reallyLongStream = new stream.Readable({
|
|
@@ -50,30 +50,30 @@ test('Destroying streams prematurely should call abort method', t => {
|
|
|
50
50
|
})
|
|
51
51
|
reallyLongStream.destroy = undefined
|
|
52
52
|
reallyLongStream.close = undefined
|
|
53
|
-
reallyLongStream.abort = () => t.ok('called')
|
|
53
|
+
reallyLongStream.abort = () => t.assert.ok('called')
|
|
54
54
|
reply.send(reallyLongStream)
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
fastify.listen({ port: 0 }, err => {
|
|
58
|
-
t.
|
|
59
|
-
t.
|
|
58
|
+
t.assert.ifError(err)
|
|
59
|
+
t.after(() => { fastify.close() })
|
|
60
60
|
|
|
61
61
|
const port = fastify.server.address().port
|
|
62
62
|
|
|
63
63
|
http.get(`http://localhost:${port}`, function (response) {
|
|
64
|
-
t.
|
|
64
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
65
65
|
response.on('readable', function () {
|
|
66
66
|
response.destroy()
|
|
67
67
|
})
|
|
68
68
|
// Node bug? Node never emits 'close' here.
|
|
69
69
|
response.on('aborted', function () {
|
|
70
|
-
t.
|
|
70
|
+
t.assert.ok('Response closed')
|
|
71
71
|
})
|
|
72
72
|
})
|
|
73
73
|
})
|
|
74
74
|
})
|
|
75
75
|
|
|
76
|
-
test('Destroying streams prematurely, log is disabled', t => {
|
|
76
|
+
test('Destroying streams prematurely, log is disabled', (t, testDone) => {
|
|
77
77
|
t.plan(4)
|
|
78
78
|
|
|
79
79
|
let fastify = null
|
|
@@ -82,7 +82,7 @@ test('Destroying streams prematurely, log is disabled', t => {
|
|
|
82
82
|
logger: false
|
|
83
83
|
})
|
|
84
84
|
} catch (e) {
|
|
85
|
-
t.fail()
|
|
85
|
+
t.assert.fail()
|
|
86
86
|
}
|
|
87
87
|
const stream = require('node:stream')
|
|
88
88
|
const http = require('node:http')
|
|
@@ -100,30 +100,33 @@ test('Destroying streams prematurely, log is disabled', t => {
|
|
|
100
100
|
}
|
|
101
101
|
})
|
|
102
102
|
reallyLongStream.destroy = true
|
|
103
|
-
reallyLongStream.close = () =>
|
|
103
|
+
reallyLongStream.close = () => {
|
|
104
|
+
t.assert.ok('called')
|
|
105
|
+
testDone()
|
|
106
|
+
}
|
|
104
107
|
reply.send(reallyLongStream)
|
|
105
108
|
})
|
|
106
109
|
|
|
107
110
|
fastify.listen({ port: 0 }, err => {
|
|
108
|
-
t.
|
|
109
|
-
t.
|
|
111
|
+
t.assert.ifError(err)
|
|
112
|
+
t.after(() => { fastify.close() })
|
|
110
113
|
|
|
111
114
|
const port = fastify.server.address().port
|
|
112
115
|
|
|
113
116
|
http.get(`http://localhost:${port}`, function (response) {
|
|
114
|
-
t.
|
|
117
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
115
118
|
response.on('readable', function () {
|
|
116
119
|
response.destroy()
|
|
117
120
|
})
|
|
118
121
|
// Node bug? Node never emits 'close' here.
|
|
119
122
|
response.on('aborted', function () {
|
|
120
|
-
t.
|
|
123
|
+
t.assert.ok('Response closed')
|
|
121
124
|
})
|
|
122
125
|
})
|
|
123
126
|
})
|
|
124
127
|
})
|
|
125
128
|
|
|
126
|
-
test('should respond with a stream1', t => {
|
|
129
|
+
test('should respond with a stream1', (t, testDone) => {
|
|
127
130
|
t.plan(5)
|
|
128
131
|
const fastify = Fastify()
|
|
129
132
|
|
|
@@ -135,25 +138,26 @@ test('should respond with a stream1', t => {
|
|
|
135
138
|
})
|
|
136
139
|
|
|
137
140
|
fastify.listen({ port: 0 }, err => {
|
|
138
|
-
t.
|
|
139
|
-
t.
|
|
141
|
+
t.assert.ifError(err)
|
|
142
|
+
t.after(() => { fastify.close() })
|
|
140
143
|
|
|
141
144
|
sget(`http://localhost:${fastify.server.address().port}`, function (err, response, body) {
|
|
142
|
-
t.
|
|
143
|
-
t.
|
|
144
|
-
t.
|
|
145
|
-
t.
|
|
145
|
+
t.assert.ifError(err)
|
|
146
|
+
t.assert.strictEqual(response.headers['content-type'], 'application/json')
|
|
147
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
148
|
+
t.assert.deepStrictEqual(JSON.parse(body), [{ hello: 'world' }, { a: 42 }])
|
|
149
|
+
testDone()
|
|
146
150
|
})
|
|
147
151
|
})
|
|
148
152
|
})
|
|
149
153
|
|
|
150
|
-
test('return a 404 if the stream emits a 404 error', t => {
|
|
154
|
+
test('return a 404 if the stream emits a 404 error', (t, testDone) => {
|
|
151
155
|
t.plan(5)
|
|
152
156
|
|
|
153
157
|
const fastify = Fastify()
|
|
154
158
|
|
|
155
159
|
fastify.get('/', function (request, reply) {
|
|
156
|
-
t.
|
|
160
|
+
t.assert.ok('Received request')
|
|
157
161
|
|
|
158
162
|
const reallyLongStream = new Readable({
|
|
159
163
|
read: function () {
|
|
@@ -167,15 +171,16 @@ test('return a 404 if the stream emits a 404 error', t => {
|
|
|
167
171
|
})
|
|
168
172
|
|
|
169
173
|
fastify.listen({ port: 0 }, err => {
|
|
170
|
-
t.
|
|
171
|
-
t.
|
|
174
|
+
t.assert.ifError(err)
|
|
175
|
+
t.after(() => { fastify.close() })
|
|
172
176
|
|
|
173
177
|
const port = fastify.server.address().port
|
|
174
178
|
|
|
175
179
|
sget(`http://localhost:${port}`, function (err, response) {
|
|
176
|
-
t.
|
|
177
|
-
t.
|
|
178
|
-
t.
|
|
180
|
+
t.assert.ifError(err)
|
|
181
|
+
t.assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
|
|
182
|
+
t.assert.strictEqual(response.statusCode, 404)
|
|
183
|
+
testDone()
|
|
179
184
|
})
|
|
180
185
|
})
|
|
181
186
|
})
|
package/test/toolkit.js
CHANGED
|
@@ -30,3 +30,34 @@ exports.waitForCb = function (options) {
|
|
|
30
30
|
|
|
31
31
|
return { stepIn, patience }
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
exports.partialDeepStrictEqual = function partialDeepStrictEqual (actual, expected) {
|
|
35
|
+
if (typeof expected !== 'object' || expected === null) {
|
|
36
|
+
return actual === expected
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof actual !== 'object' || actual === null) {
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (Array.isArray(expected)) {
|
|
44
|
+
if (!Array.isArray(actual)) return false
|
|
45
|
+
if (expected.length > actual.length) return false
|
|
46
|
+
|
|
47
|
+
for (let i = 0; i < expected.length; i++) {
|
|
48
|
+
if (!partialDeepStrictEqual(actual[i], expected[i])) {
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return true
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (const key of Object.keys(expected)) {
|
|
56
|
+
if (!(key in actual)) return false
|
|
57
|
+
if (!partialDeepStrictEqual(actual[key], expected[key])) {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return true
|
|
63
|
+
}
|