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
|
@@ -4,7 +4,7 @@ const stream = require('node:stream')
|
|
|
4
4
|
const os = require('node:os')
|
|
5
5
|
const fs = require('node:fs')
|
|
6
6
|
|
|
7
|
-
const t = require('
|
|
7
|
+
const t = require('node:test')
|
|
8
8
|
const split = require('split2')
|
|
9
9
|
|
|
10
10
|
const { streamSym } = require('pino/lib/symbols')
|
|
@@ -14,10 +14,9 @@ const helper = require('../helper')
|
|
|
14
14
|
const { FST_ERR_LOG_INVALID_LOGGER } = require('../../lib/errors')
|
|
15
15
|
const { once, on } = stream
|
|
16
16
|
const { createTempFile, request } = require('./logger-test-utils')
|
|
17
|
+
const { partialDeepStrictEqual } = require('../toolkit')
|
|
17
18
|
|
|
18
|
-
t.test('logger instantiation', (t) => {
|
|
19
|
-
t.setTimeout(60000)
|
|
20
|
-
|
|
19
|
+
t.test('logger instantiation', { timeout: 60000 }, async (t) => {
|
|
21
20
|
let localhost
|
|
22
21
|
let localhostForURL
|
|
23
22
|
|
|
@@ -26,7 +25,7 @@ t.test('logger instantiation', (t) => {
|
|
|
26
25
|
[localhost, localhostForURL] = await helper.getLoopbackHost()
|
|
27
26
|
})
|
|
28
27
|
|
|
29
|
-
t.test('can use external logger instance', async (t) => {
|
|
28
|
+
await t.test('can use external logger instance', async (t) => {
|
|
30
29
|
const lines = [/^Server listening at /, /^incoming request$/, /^log success$/, /^request completed$/]
|
|
31
30
|
t.plan(lines.length + 1)
|
|
32
31
|
|
|
@@ -35,10 +34,10 @@ t.test('logger instantiation', (t) => {
|
|
|
35
34
|
const loggerInstance = require('pino')(stream)
|
|
36
35
|
|
|
37
36
|
const fastify = Fastify({ loggerInstance })
|
|
38
|
-
t.
|
|
37
|
+
t.after(() => fastify.close())
|
|
39
38
|
|
|
40
39
|
fastify.get('/foo', function (req, reply) {
|
|
41
|
-
t.ok(req.log)
|
|
40
|
+
t.assert.ok(req.log)
|
|
42
41
|
req.log.info('log success')
|
|
43
42
|
reply.send({ hello: 'world' })
|
|
44
43
|
})
|
|
@@ -49,30 +48,30 @@ t.test('logger instantiation', (t) => {
|
|
|
49
48
|
|
|
50
49
|
for await (const [line] of on(stream, 'data')) {
|
|
51
50
|
const regex = lines.shift()
|
|
52
|
-
t.ok(regex.test(line.msg), '"' + line.msg + '" does not match "' + regex + '"')
|
|
51
|
+
t.assert.ok(regex.test(line.msg), '"' + line.msg + '" does not match "' + regex + '"')
|
|
53
52
|
if (lines.length === 0) break
|
|
54
53
|
}
|
|
55
54
|
})
|
|
56
55
|
|
|
57
|
-
t.test('should create a default logger if provided one is invalid', (t) => {
|
|
56
|
+
await t.test('should create a default logger if provided one is invalid', (t) => {
|
|
58
57
|
t.plan(8)
|
|
59
58
|
|
|
60
59
|
const logger = new Date()
|
|
61
60
|
|
|
62
61
|
const fastify = Fastify({ logger })
|
|
63
|
-
t.
|
|
64
|
-
|
|
65
|
-
t.
|
|
66
|
-
t.
|
|
67
|
-
t.
|
|
68
|
-
t.
|
|
69
|
-
t.
|
|
70
|
-
t.
|
|
71
|
-
t.
|
|
72
|
-
t.
|
|
62
|
+
t.after(() => fastify.close())
|
|
63
|
+
|
|
64
|
+
t.assert.strictEqual(typeof fastify.log, 'object')
|
|
65
|
+
t.assert.strictEqual(typeof fastify.log.fatal, 'function')
|
|
66
|
+
t.assert.strictEqual(typeof fastify.log.error, 'function')
|
|
67
|
+
t.assert.strictEqual(typeof fastify.log.warn, 'function')
|
|
68
|
+
t.assert.strictEqual(typeof fastify.log.info, 'function')
|
|
69
|
+
t.assert.strictEqual(typeof fastify.log.debug, 'function')
|
|
70
|
+
t.assert.strictEqual(typeof fastify.log.trace, 'function')
|
|
71
|
+
t.assert.strictEqual(typeof fastify.log.child, 'function')
|
|
73
72
|
})
|
|
74
73
|
|
|
75
|
-
t.test('expose the logger', async (t) => {
|
|
74
|
+
await t.test('expose the logger', async (t) => {
|
|
76
75
|
t.plan(2)
|
|
77
76
|
const stream = split(JSON.parse)
|
|
78
77
|
const fastify = Fastify({
|
|
@@ -81,49 +80,45 @@ t.test('logger instantiation', (t) => {
|
|
|
81
80
|
level: 'info'
|
|
82
81
|
}
|
|
83
82
|
})
|
|
84
|
-
t.
|
|
83
|
+
t.after(() => fastify.close())
|
|
85
84
|
|
|
86
85
|
await fastify.ready()
|
|
87
86
|
|
|
88
|
-
t.ok(fastify.log)
|
|
89
|
-
t.
|
|
87
|
+
t.assert.ok(fastify.log)
|
|
88
|
+
t.assert.strictEqual(typeof fastify.log, 'object')
|
|
90
89
|
})
|
|
91
90
|
|
|
92
|
-
|
|
91
|
+
const interfaces = os.networkInterfaces()
|
|
92
|
+
const ipv6 = Object.keys(interfaces)
|
|
93
|
+
.filter(name => name.substr(0, 2) === 'lo')
|
|
94
|
+
.map(name => interfaces[name])
|
|
95
|
+
.reduce((list, set) => list.concat(set), [])
|
|
96
|
+
.filter(info => info.family === 'IPv6')
|
|
97
|
+
.map(info => info.address)
|
|
98
|
+
.shift()
|
|
99
|
+
|
|
100
|
+
await t.test('Wrap IPv6 address in listening log message', { skip: !ipv6 }, async (t) => {
|
|
93
101
|
t.plan(1)
|
|
94
102
|
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (ipv6 === undefined) {
|
|
105
|
-
t.pass('No IPv6 loopback interface')
|
|
106
|
-
} else {
|
|
107
|
-
const stream = split(JSON.parse)
|
|
108
|
-
const fastify = Fastify({
|
|
109
|
-
logger: {
|
|
110
|
-
stream,
|
|
111
|
-
level: 'info'
|
|
112
|
-
}
|
|
113
|
-
})
|
|
114
|
-
t.teardown(fastify.close.bind(fastify))
|
|
103
|
+
const stream = split(JSON.parse)
|
|
104
|
+
const fastify = Fastify({
|
|
105
|
+
logger: {
|
|
106
|
+
stream,
|
|
107
|
+
level: 'info'
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
t.after(() => fastify.close())
|
|
115
111
|
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
await fastify.ready()
|
|
113
|
+
await fastify.listen({ port: 0, host: ipv6 })
|
|
118
114
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
115
|
+
{
|
|
116
|
+
const [line] = await once(stream, 'data')
|
|
117
|
+
t.assert.strictEqual(line.msg, `Server listening at http://[${ipv6}]:${fastify.server.address().port}`)
|
|
123
118
|
}
|
|
124
119
|
})
|
|
125
120
|
|
|
126
|
-
t.test('Do not wrap IPv4 address', async (t) => {
|
|
121
|
+
await t.test('Do not wrap IPv4 address', async (t) => {
|
|
127
122
|
t.plan(1)
|
|
128
123
|
const stream = split(JSON.parse)
|
|
129
124
|
const fastify = Fastify({
|
|
@@ -132,24 +127,18 @@ t.test('logger instantiation', (t) => {
|
|
|
132
127
|
level: 'info'
|
|
133
128
|
}
|
|
134
129
|
})
|
|
135
|
-
t.
|
|
130
|
+
t.after(() => fastify.close())
|
|
136
131
|
|
|
137
132
|
await fastify.ready()
|
|
138
133
|
await fastify.listen({ port: 0, host: '127.0.0.1' })
|
|
139
134
|
|
|
140
135
|
{
|
|
141
136
|
const [line] = await once(stream, 'data')
|
|
142
|
-
t.
|
|
137
|
+
t.assert.strictEqual(line.msg, `Server listening at http://127.0.0.1:${fastify.server.address().port}`)
|
|
143
138
|
}
|
|
144
139
|
})
|
|
145
140
|
|
|
146
|
-
t.test('file option', async (t) => {
|
|
147
|
-
const lines = [
|
|
148
|
-
{ msg: /Server listening at/ },
|
|
149
|
-
{ reqId: /req-/, req: { method: 'GET', url: '/' }, msg: 'incoming request' },
|
|
150
|
-
{ reqId: /req-/, res: { statusCode: 200 }, msg: 'request completed' }
|
|
151
|
-
]
|
|
152
|
-
|
|
141
|
+
await t.test('file option', async (t) => {
|
|
153
142
|
const { file, cleanup } = createTempFile(t)
|
|
154
143
|
// 0600 permissions (read/write for owner only)
|
|
155
144
|
if (process.env.CITGM) { fs.writeFileSync(file, '', { mode: 0o600 }) }
|
|
@@ -158,7 +147,7 @@ t.test('logger instantiation', (t) => {
|
|
|
158
147
|
logger: { file }
|
|
159
148
|
})
|
|
160
149
|
|
|
161
|
-
t.
|
|
150
|
+
t.after(async () => {
|
|
162
151
|
await helper.sleep(250)
|
|
163
152
|
// may fail on win
|
|
164
153
|
try {
|
|
@@ -174,15 +163,20 @@ t.test('logger instantiation', (t) => {
|
|
|
174
163
|
console.warn(err)
|
|
175
164
|
}
|
|
176
165
|
})
|
|
177
|
-
t.
|
|
166
|
+
t.after(() => fastify.close())
|
|
178
167
|
|
|
179
168
|
fastify.get('/', function (req, reply) {
|
|
180
|
-
t.ok(req.log)
|
|
169
|
+
t.assert.ok(req.log)
|
|
181
170
|
reply.send({ hello: 'world' })
|
|
182
171
|
})
|
|
183
172
|
|
|
184
173
|
await fastify.ready()
|
|
185
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
174
|
+
const server = await fastify.listen({ port: 0, host: localhost })
|
|
175
|
+
const lines = [
|
|
176
|
+
{ msg: `Server listening at ${server}` },
|
|
177
|
+
{ req: { method: 'GET', url: '/' }, msg: 'incoming request' },
|
|
178
|
+
{ res: { statusCode: 200 }, msg: 'request completed' }
|
|
179
|
+
]
|
|
186
180
|
await request(`http://${localhostForURL}:` + fastify.server.address().port)
|
|
187
181
|
|
|
188
182
|
await helper.sleep(250)
|
|
@@ -195,26 +189,26 @@ t.test('logger instantiation', (t) => {
|
|
|
195
189
|
for (let line of log) {
|
|
196
190
|
line = JSON.parse(line)
|
|
197
191
|
if (id === undefined && line.reqId) id = line.reqId
|
|
198
|
-
if (id !== undefined && line.reqId) t.
|
|
199
|
-
t.
|
|
192
|
+
if (id !== undefined && line.reqId) t.assert.strictEqual(line.reqId, id)
|
|
193
|
+
t.assert.ok(partialDeepStrictEqual(line, lines.shift()))
|
|
200
194
|
}
|
|
201
195
|
})
|
|
202
196
|
|
|
203
|
-
t.test('should be able to use a custom logger', (t) => {
|
|
197
|
+
await t.test('should be able to use a custom logger', (t) => {
|
|
204
198
|
t.plan(7)
|
|
205
199
|
|
|
206
200
|
const loggerInstance = {
|
|
207
|
-
fatal: (msg) => { t.
|
|
208
|
-
error: (msg) => { t.
|
|
209
|
-
warn: (msg) => { t.
|
|
210
|
-
info: (msg) => { t.
|
|
211
|
-
debug: (msg) => { t.
|
|
212
|
-
trace: (msg) => { t.
|
|
201
|
+
fatal: (msg) => { t.assert.strictEqual(msg, 'fatal') },
|
|
202
|
+
error: (msg) => { t.assert.strictEqual(msg, 'error') },
|
|
203
|
+
warn: (msg) => { t.assert.strictEqual(msg, 'warn') },
|
|
204
|
+
info: (msg) => { t.assert.strictEqual(msg, 'info') },
|
|
205
|
+
debug: (msg) => { t.assert.strictEqual(msg, 'debug') },
|
|
206
|
+
trace: (msg) => { t.assert.strictEqual(msg, 'trace') },
|
|
213
207
|
child: () => loggerInstance
|
|
214
208
|
}
|
|
215
209
|
|
|
216
210
|
const fastify = Fastify({ loggerInstance })
|
|
217
|
-
t.
|
|
211
|
+
t.after(() => fastify.close())
|
|
218
212
|
|
|
219
213
|
fastify.log.fatal('fatal')
|
|
220
214
|
fastify.log.error('error')
|
|
@@ -223,17 +217,17 @@ t.test('logger instantiation', (t) => {
|
|
|
223
217
|
fastify.log.debug('debug')
|
|
224
218
|
fastify.log.trace('trace')
|
|
225
219
|
const child = fastify.log.child()
|
|
226
|
-
t.
|
|
220
|
+
t.assert.strictEqual(child, loggerInstance)
|
|
227
221
|
})
|
|
228
222
|
|
|
229
|
-
t.test('should throw in case a partially matching logger is provided', async (t) => {
|
|
223
|
+
await t.test('should throw in case a partially matching logger is provided', async (t) => {
|
|
230
224
|
t.plan(1)
|
|
231
225
|
|
|
232
226
|
try {
|
|
233
227
|
const fastify = Fastify({ logger: console })
|
|
234
228
|
await fastify.ready()
|
|
235
229
|
} catch (err) {
|
|
236
|
-
t.
|
|
230
|
+
t.assert.strictEqual(
|
|
237
231
|
err instanceof FST_ERR_LOG_INVALID_LOGGER,
|
|
238
232
|
true,
|
|
239
233
|
"Invalid logger object provided. The logger instance should have these functions(s): 'fatal,child'."
|
|
@@ -241,7 +235,7 @@ t.test('logger instantiation', (t) => {
|
|
|
241
235
|
}
|
|
242
236
|
})
|
|
243
237
|
|
|
244
|
-
t.test('can use external logger instance with custom serializer', async (t) => {
|
|
238
|
+
await t.test('can use external logger instance with custom serializer', async (t) => {
|
|
245
239
|
const lines = [['level', 30], ['req', { url: '/foo' }], ['level', 30], ['res', { statusCode: 200 }]]
|
|
246
240
|
t.plan(lines.length + 1)
|
|
247
241
|
|
|
@@ -260,10 +254,10 @@ t.test('logger instantiation', (t) => {
|
|
|
260
254
|
const fastify = Fastify({
|
|
261
255
|
loggerInstance
|
|
262
256
|
})
|
|
263
|
-
t.
|
|
257
|
+
t.after(() => fastify.close())
|
|
264
258
|
|
|
265
259
|
fastify.get('/foo', function (req, reply) {
|
|
266
|
-
t.ok(req.log)
|
|
260
|
+
t.assert.ok(req.log)
|
|
267
261
|
req.log.info('log success')
|
|
268
262
|
reply.send({ hello: 'world' })
|
|
269
263
|
})
|
|
@@ -277,20 +271,12 @@ t.test('logger instantiation', (t) => {
|
|
|
277
271
|
const check = lines.shift()
|
|
278
272
|
const key = check[0]
|
|
279
273
|
const value = check[1]
|
|
280
|
-
t.
|
|
274
|
+
t.assert.deepStrictEqual(line[key], value)
|
|
281
275
|
if (lines.length === 0) break
|
|
282
276
|
}
|
|
283
277
|
})
|
|
284
278
|
|
|
285
|
-
t.test('The logger should accept custom serializer', async (t) => {
|
|
286
|
-
const lines = [
|
|
287
|
-
{ msg: /^Server listening at / },
|
|
288
|
-
{ req: { url: '/custom' }, msg: 'incoming request' },
|
|
289
|
-
{ res: { statusCode: 500 }, msg: 'kaboom' },
|
|
290
|
-
{ res: { statusCode: 500 }, msg: 'request completed' }
|
|
291
|
-
]
|
|
292
|
-
t.plan(lines.length + 1)
|
|
293
|
-
|
|
279
|
+
await t.test('The logger should accept custom serializer', async (t) => {
|
|
294
280
|
const stream = split(JSON.parse)
|
|
295
281
|
const fastify = Fastify({
|
|
296
282
|
logger: {
|
|
@@ -305,25 +291,32 @@ t.test('logger instantiation', (t) => {
|
|
|
305
291
|
}
|
|
306
292
|
}
|
|
307
293
|
})
|
|
308
|
-
t.
|
|
294
|
+
t.after(() => fastify.close())
|
|
309
295
|
|
|
310
296
|
fastify.get('/custom', function (req, reply) {
|
|
311
|
-
t.ok(req.log)
|
|
297
|
+
t.assert.ok(req.log)
|
|
312
298
|
reply.send(new Error('kaboom'))
|
|
313
299
|
})
|
|
314
300
|
|
|
315
301
|
await fastify.ready()
|
|
316
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
302
|
+
const server = await fastify.listen({ port: 0, host: localhost })
|
|
303
|
+
const lines = [
|
|
304
|
+
{ msg: `Server listening at ${server}` },
|
|
305
|
+
{ req: { url: '/custom' }, msg: 'incoming request' },
|
|
306
|
+
{ res: { statusCode: 500 }, msg: 'kaboom' },
|
|
307
|
+
{ res: { statusCode: 500 }, msg: 'request completed' }
|
|
308
|
+
]
|
|
309
|
+
t.plan(lines.length + 1)
|
|
317
310
|
|
|
318
311
|
await request(`http://${localhostForURL}:` + fastify.server.address().port + '/custom')
|
|
319
312
|
|
|
320
313
|
for await (const [line] of on(stream, 'data')) {
|
|
321
|
-
t.
|
|
314
|
+
t.assert.ok(partialDeepStrictEqual(line, lines.shift()))
|
|
322
315
|
if (lines.length === 0) break
|
|
323
316
|
}
|
|
324
317
|
})
|
|
325
318
|
|
|
326
|
-
t.test('should throw in case the external logger provided does not have a child method', async (t) => {
|
|
319
|
+
await t.test('should throw in case the external logger provided does not have a child method', async (t) => {
|
|
327
320
|
t.plan(1)
|
|
328
321
|
const loggerInstance = {
|
|
329
322
|
info: console.info,
|
|
@@ -338,7 +331,7 @@ t.test('logger instantiation', (t) => {
|
|
|
338
331
|
const fastify = Fastify({ logger: loggerInstance })
|
|
339
332
|
await fastify.ready()
|
|
340
333
|
} catch (err) {
|
|
341
|
-
t.
|
|
334
|
+
t.assert.strictEqual(
|
|
342
335
|
err instanceof FST_ERR_LOG_INVALID_LOGGER,
|
|
343
336
|
true,
|
|
344
337
|
"Invalid logger object provided. The logger instance should have these functions(s): 'child'."
|