fastify 3.26.0 → 4.0.0-alpha.1

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.
Files changed (129) hide show
  1. package/README.md +5 -4
  2. package/build/build-error-serializer.js +27 -0
  3. package/build/build-validation.js +49 -35
  4. package/docs/Guides/Ecosystem.md +2 -1
  5. package/docs/Guides/Prototype-Poisoning.md +3 -3
  6. package/docs/Migration-Guide-V4.md +12 -0
  7. package/docs/Reference/ContentTypeParser.md +8 -1
  8. package/docs/Reference/Errors.md +51 -6
  9. package/docs/Reference/Hooks.md +4 -7
  10. package/docs/Reference/LTS.md +5 -4
  11. package/docs/Reference/Reply.md +23 -22
  12. package/docs/Reference/Request.md +1 -3
  13. package/docs/Reference/Routes.md +17 -10
  14. package/docs/Reference/Server.md +98 -63
  15. package/docs/Reference/TypeScript.md +11 -13
  16. package/docs/Reference/Validation-and-Serialization.md +32 -54
  17. package/docs/Type-Providers.md +257 -0
  18. package/examples/hooks.js +1 -1
  19. package/examples/simple-stream.js +18 -0
  20. package/fastify.d.ts +36 -22
  21. package/fastify.js +72 -53
  22. package/lib/configValidator.js +902 -1023
  23. package/lib/contentTypeParser.js +6 -16
  24. package/lib/context.js +36 -10
  25. package/lib/decorate.js +5 -3
  26. package/lib/error-handler.js +158 -0
  27. package/lib/error-serializer.js +257 -0
  28. package/lib/errors.js +49 -10
  29. package/lib/fourOhFour.js +31 -20
  30. package/lib/handleRequest.js +10 -13
  31. package/lib/hooks.js +14 -9
  32. package/lib/noop-set.js +10 -0
  33. package/lib/pluginOverride.js +0 -3
  34. package/lib/pluginUtils.js +3 -2
  35. package/lib/reply.js +44 -163
  36. package/lib/request.js +13 -10
  37. package/lib/route.js +158 -139
  38. package/lib/schema-controller.js +3 -3
  39. package/lib/schemas.js +27 -1
  40. package/lib/server.js +219 -116
  41. package/lib/symbols.js +6 -4
  42. package/lib/validation.js +2 -1
  43. package/lib/warnings.js +2 -12
  44. package/lib/wrapThenable.js +4 -11
  45. package/package.json +40 -45
  46. package/test/404s.test.js +265 -108
  47. package/test/500s.test.js +2 -2
  48. package/test/async-await.test.js +15 -71
  49. package/test/close.test.js +39 -1
  50. package/test/content-parser.test.js +32 -0
  51. package/test/context-config.test.js +56 -4
  52. package/test/custom-http-server.test.js +14 -7
  53. package/test/custom-parser-async.test.js +0 -65
  54. package/test/custom-parser.test.js +54 -121
  55. package/test/decorator.test.js +1 -3
  56. package/test/delete.test.js +5 -5
  57. package/test/encapsulated-error-handler.test.js +50 -0
  58. package/test/esm/index.test.js +0 -14
  59. package/test/fastify-instance.test.js +4 -4
  60. package/test/fluent-schema.test.js +4 -4
  61. package/test/get.test.js +3 -3
  62. package/test/helper.js +18 -3
  63. package/test/hooks-async.test.js +14 -47
  64. package/test/hooks.on-ready.test.js +9 -4
  65. package/test/hooks.test.js +58 -99
  66. package/test/http2/closing.test.js +5 -11
  67. package/test/http2/unknown-http-method.test.js +3 -9
  68. package/test/https/custom-https-server.test.js +12 -6
  69. package/test/inject.test.js +1 -1
  70. package/test/input-validation.js +2 -2
  71. package/test/internals/all.test.js +2 -2
  72. package/test/internals/contentTypeParser.test.js +4 -4
  73. package/test/internals/handleRequest.test.js +9 -46
  74. package/test/internals/initialConfig.test.js +33 -12
  75. package/test/internals/logger.test.js +1 -1
  76. package/test/internals/reply.test.js +245 -3
  77. package/test/internals/request.test.js +13 -7
  78. package/test/internals/server.test.js +88 -0
  79. package/test/listen.test.js +84 -1
  80. package/test/logger.test.js +98 -58
  81. package/test/maxRequestsPerSocket.test.js +8 -6
  82. package/test/middleware.test.js +2 -25
  83. package/test/noop-set.test.js +19 -0
  84. package/test/nullable-validation.test.js +51 -14
  85. package/test/plugin.test.js +31 -5
  86. package/test/pretty-print.test.js +22 -10
  87. package/test/reply-error.test.js +123 -12
  88. package/test/request-error.test.js +2 -5
  89. package/test/route-hooks.test.js +17 -17
  90. package/test/route-prefix.test.js +2 -1
  91. package/test/route.test.js +216 -20
  92. package/test/router-options.test.js +1 -1
  93. package/test/schema-examples.test.js +11 -5
  94. package/test/schema-feature.test.js +24 -19
  95. package/test/schema-serialization.test.js +50 -9
  96. package/test/schema-special-usage.test.js +14 -81
  97. package/test/schema-validation.test.js +9 -9
  98. package/test/skip-reply-send.test.js +8 -8
  99. package/test/stream.test.js +23 -12
  100. package/test/throw.test.js +8 -5
  101. package/test/trust-proxy.test.js +1 -1
  102. package/test/type-provider.test.js +20 -0
  103. package/test/types/fastify.test-d.ts +12 -18
  104. package/test/types/hooks.test-d.ts +7 -3
  105. package/test/types/import.js +2 -0
  106. package/test/types/import.ts +1 -0
  107. package/test/types/instance.test-d.ts +61 -15
  108. package/test/types/logger.test-d.ts +44 -15
  109. package/test/types/route.test-d.ts +8 -2
  110. package/test/types/schema.test-d.ts +2 -39
  111. package/test/types/type-provider.test-d.ts +417 -0
  112. package/test/validation-error-handling.test.js +9 -9
  113. package/test/versioned-routes.test.js +29 -17
  114. package/test/wrapThenable.test.js +7 -6
  115. package/types/.eslintrc.json +1 -1
  116. package/types/content-type-parser.d.ts +17 -8
  117. package/types/hooks.d.ts +107 -60
  118. package/types/instance.d.ts +137 -105
  119. package/types/logger.d.ts +18 -104
  120. package/types/plugin.d.ts +10 -4
  121. package/types/register.d.ts +1 -1
  122. package/types/reply.d.ts +16 -11
  123. package/types/request.d.ts +10 -5
  124. package/types/route.d.ts +42 -31
  125. package/types/schema.d.ts +15 -1
  126. package/types/type-provider.d.ts +99 -0
  127. package/types/utils.d.ts +1 -1
  128. package/lib/schema-compilers.js +0 -12
  129. package/test/emit-warning.test.js +0 -166
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const { test, teardown } = require('tap')
3
+ const { test, teardown, before } = require('tap')
4
+ const helper = require('./helper')
4
5
  const http = require('http')
5
6
  const stream = require('stream')
6
7
  const split = require('split2')
@@ -10,9 +11,12 @@ const path = require('path')
10
11
  const os = require('os')
11
12
  const fs = require('fs')
12
13
  const sget = require('simple-get').concat
14
+ const dns = require('dns')
13
15
 
14
16
  const files = []
15
17
  let count = 0
18
+ let localhost
19
+ let localhostForURL
16
20
 
17
21
  function file () {
18
22
  const file = path.join(os.tmpdir(), `sonic-boom-${process.pid}-${process.hrtime().toString()}-${count++}`)
@@ -20,6 +24,10 @@ function file () {
20
24
  return file
21
25
  }
22
26
 
27
+ before(async function () {
28
+ [localhost, localhostForURL] = await helper.getLoopbackHost()
29
+ })
30
+
23
31
  teardown(() => {
24
32
  files.forEach((file) => {
25
33
  try {
@@ -31,13 +39,12 @@ teardown(() => {
31
39
  })
32
40
 
33
41
  test('defaults to info level', t => {
34
- t.plan(13)
35
42
  let fastify = null
36
43
  const stream = split(JSON.parse)
37
44
  try {
38
45
  fastify = Fastify({
39
46
  logger: {
40
- stream: stream
47
+ stream
41
48
  }
42
49
  })
43
50
  } catch (e) {
@@ -49,9 +56,28 @@ test('defaults to info level', t => {
49
56
  reply.send({ hello: 'world' })
50
57
  })
51
58
 
52
- stream.once('data', listenAtLogLine => {
53
- t.ok(listenAtLogLine, 'listen at log message is ok')
59
+ fastify.listen(0, err => {
60
+ t.error(err)
61
+ fastify.server.unref()
62
+
63
+ dns.lookup('localhost', { all: true }, function (err, addresses) {
64
+ t.error(err)
65
+ let toSkip = addresses.length
66
+
67
+ function skip (data) {
68
+ if (--toSkip === 0) {
69
+ stream.removeListener('data', skip)
70
+ check()
71
+ }
72
+ }
73
+
74
+ stream.on('data', skip)
54
75
 
76
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port)
77
+ })
78
+ })
79
+
80
+ function check () {
55
81
  stream.once('data', line => {
56
82
  const id = line.reqId
57
83
  t.ok(line.reqId, 'reqId is defined')
@@ -66,16 +92,10 @@ test('defaults to info level', t => {
66
92
  t.equal(line.msg, 'request completed', 'message is set')
67
93
  t.equal(line.res.statusCode, 200, 'statusCode is 200')
68
94
  t.ok(line.responseTime, 'responseTime is defined')
95
+ t.end()
69
96
  })
70
97
  })
71
- })
72
-
73
- fastify.listen(0, err => {
74
- t.error(err)
75
- fastify.server.unref()
76
-
77
- http.get('http://localhost:' + fastify.server.address().port)
78
- })
98
+ }
79
99
  })
80
100
 
81
101
  test('test log stream', t => {
@@ -85,7 +105,7 @@ test('test log stream', t => {
85
105
  try {
86
106
  fastify = Fastify({
87
107
  logger: {
88
- stream: stream,
108
+ stream,
89
109
  level: 'info'
90
110
  }
91
111
  })
@@ -98,11 +118,11 @@ test('test log stream', t => {
98
118
  reply.send({ hello: 'world' })
99
119
  })
100
120
 
101
- fastify.listen(0, err => {
121
+ fastify.listen(0, localhost, err => {
102
122
  t.error(err)
103
123
  fastify.server.unref()
104
124
 
105
- http.get('http://localhost:' + fastify.server.address().port)
125
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port)
106
126
  stream.once('data', listenAtLogLine => {
107
127
  t.ok(listenAtLogLine, 'listen at log message is ok')
108
128
 
@@ -132,7 +152,7 @@ test('test error log stream', t => {
132
152
  try {
133
153
  fastify = Fastify({
134
154
  logger: {
135
- stream: stream,
155
+ stream,
136
156
  level: 'info'
137
157
  }
138
158
  })
@@ -145,11 +165,11 @@ test('test error log stream', t => {
145
165
  reply.send(new Error('kaboom'))
146
166
  })
147
167
 
148
- fastify.listen(0, err => {
168
+ fastify.listen(0, localhost, err => {
149
169
  t.error(err)
150
170
  fastify.server.unref()
151
171
 
152
- http.get('http://localhost:' + fastify.server.address().port + '/error')
172
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/error')
153
173
  stream.once('data', listenAtLogLine => {
154
174
  t.ok(listenAtLogLine, 'listen at log message is ok')
155
175
 
@@ -182,7 +202,7 @@ test('can use external logger instance', t => {
182
202
 
183
203
  const logger = require('pino')(splitStream)
184
204
 
185
- const localFastify = Fastify({ logger: logger })
205
+ const localFastify = Fastify({ logger })
186
206
 
187
207
  localFastify.get('/foo', function (req, reply) {
188
208
  t.ok(req.log)
@@ -190,9 +210,9 @@ test('can use external logger instance', t => {
190
210
  reply.send({ hello: 'world' })
191
211
  })
192
212
 
193
- localFastify.listen(0, err => {
213
+ localFastify.listen(0, localhost, err => {
194
214
  t.error(err)
195
- http.get('http://localhost:' + localFastify.server.address().port + '/foo', (res) => {
215
+ http.get(`http://${localhostForURL}:` + localFastify.server.address().port + '/foo', (res) => {
196
216
  res.resume()
197
217
  res.on('end', () => {
198
218
  localFastify.server.close()
@@ -226,7 +246,7 @@ test('can use external logger instance with custom serializer', t => {
226
246
  }, splitStream)
227
247
 
228
248
  const localFastify = Fastify({
229
- logger: logger
249
+ logger
230
250
  })
231
251
 
232
252
  localFastify.get('/foo', function (req, reply) {
@@ -235,9 +255,9 @@ test('can use external logger instance with custom serializer', t => {
235
255
  reply.send({ hello: 'world' })
236
256
  })
237
257
 
238
- localFastify.listen(0, err => {
258
+ localFastify.listen(0, localhost, err => {
239
259
  t.error(err)
240
- http.get('http://localhost:' + localFastify.server.address().port + '/foo', (res) => {
260
+ http.get(`http://${localhostForURL}:` + localFastify.server.address().port + '/foo', (res) => {
241
261
  res.resume()
242
262
  res.on('end', () => {
243
263
  localFastify.server.close()
@@ -253,7 +273,7 @@ test('expose the logger', t => {
253
273
  try {
254
274
  fastify = Fastify({
255
275
  logger: {
256
- stream: stream,
276
+ stream,
257
277
  level: 'info'
258
278
  }
259
279
  })
@@ -271,7 +291,7 @@ test('The request id header key can be customized', t => {
271
291
 
272
292
  const stream = split(JSON.parse)
273
293
  const fastify = Fastify({
274
- logger: { stream: stream, level: 'info' },
294
+ logger: { stream, level: 'info' },
275
295
  requestIdHeader: 'my-custom-request-id'
276
296
  })
277
297
  t.teardown(() => fastify.close())
@@ -316,7 +336,7 @@ test('The request id header key can be customized along with a custom id generat
316
336
 
317
337
  const stream = split(JSON.parse)
318
338
  const fastify = Fastify({
319
- logger: { stream: stream, level: 'info' },
339
+ logger: { stream, level: 'info' },
320
340
  requestIdHeader: 'my-custom-request-id',
321
341
  genReqId (req) {
322
342
  return 'foo'
@@ -379,7 +399,7 @@ test('The request id log label can be changed', t => {
379
399
 
380
400
  const stream = split(JSON.parse)
381
401
  const fastify = Fastify({
382
- logger: { stream: stream, level: 'info' },
402
+ logger: { stream, level: 'info' },
383
403
  requestIdHeader: 'my-custom-request-id',
384
404
  requestIdLogLabel: 'traceId'
385
405
  })
@@ -422,7 +442,7 @@ test('The logger should accept custom serializer', t => {
422
442
  const stream = split(JSON.parse)
423
443
  const fastify = Fastify({
424
444
  logger: {
425
- stream: stream,
445
+ stream,
426
446
  level: 'info',
427
447
  serializers: {
428
448
  req: function (req) {
@@ -439,11 +459,11 @@ test('The logger should accept custom serializer', t => {
439
459
  reply.send(new Error('kaboom'))
440
460
  })
441
461
 
442
- fastify.listen(0, err => {
462
+ fastify.listen(0, localhost, err => {
443
463
  t.error(err)
444
464
  fastify.server.unref()
445
465
 
446
- http.get('http://localhost:' + fastify.server.address().port + '/custom')
466
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/custom')
447
467
  stream.once('data', listenAtLogLine => {
448
468
  t.ok(listenAtLogLine, 'listen at log message is ok')
449
469
 
@@ -1151,7 +1171,7 @@ test('should serialize request and response', t => {
1151
1171
  const stream = split(JSON.parse)
1152
1172
  const fastify = Fastify({
1153
1173
  logger: {
1154
- stream: stream,
1174
+ stream,
1155
1175
  level: 'info'
1156
1176
  }
1157
1177
  })
@@ -1173,7 +1193,7 @@ test('Do not wrap IPv4 address', t => {
1173
1193
  const stream = split(JSON.parse)
1174
1194
  const fastify = Fastify({
1175
1195
  logger: {
1176
- stream: stream,
1196
+ stream,
1177
1197
  level: 'info'
1178
1198
  }
1179
1199
  })
@@ -1204,11 +1224,11 @@ test('file option', t => {
1204
1224
  reply.send({ hello: 'world' })
1205
1225
  })
1206
1226
 
1207
- fastify.listen(0, err => {
1227
+ fastify.listen(0, localhost, err => {
1208
1228
  t.error(err)
1209
1229
  fastify.server.unref()
1210
1230
 
1211
- http.get('http://localhost:' + fastify.server.address().port, () => {
1231
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port, () => {
1212
1232
  const stream = fs.createReadStream(dest).pipe(split(JSON.parse))
1213
1233
 
1214
1234
  stream.once('data', listenAtLogLine => {
@@ -1241,7 +1261,7 @@ test('should log the error if no error handler is defined', t => {
1241
1261
  const stream = split(JSON.parse)
1242
1262
  const fastify = Fastify({
1243
1263
  logger: {
1244
- stream: stream,
1264
+ stream,
1245
1265
  level: 'info'
1246
1266
  }
1247
1267
  })
@@ -1249,10 +1269,10 @@ test('should log the error if no error handler is defined', t => {
1249
1269
  t.ok(req.log)
1250
1270
  reply.send(new Error('a generic error'))
1251
1271
  })
1252
- fastify.listen(0, err => {
1272
+ fastify.listen(0, localhost, err => {
1253
1273
  t.error(err)
1254
1274
  fastify.server.unref()
1255
- http.get('http://localhost:' + fastify.server.address().port + '/error')
1275
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/error')
1256
1276
  stream.once('data', listenAtLogLine => {
1257
1277
  t.ok(listenAtLogLine, 'listen at log message is ok')
1258
1278
  stream.once('data', line => {
@@ -1275,7 +1295,7 @@ test('should log as info if error status code >= 400 and < 500 if no error handl
1275
1295
  const stream = split(JSON.parse)
1276
1296
  const fastify = Fastify({
1277
1297
  logger: {
1278
- stream: stream,
1298
+ stream,
1279
1299
  level: 'info'
1280
1300
  }
1281
1301
  })
@@ -1287,10 +1307,10 @@ test('should log as info if error status code >= 400 and < 500 if no error handl
1287
1307
  t.ok(req.log)
1288
1308
  reply.send(Object.assign(new Error('a 503 error'), { statusCode: 503 }))
1289
1309
  })
1290
- fastify.listen(0, err => {
1310
+ fastify.listen(0, localhost, err => {
1291
1311
  t.error(err)
1292
1312
  fastify.server.unref()
1293
- http.get('http://localhost:' + fastify.server.address().port + '/400')
1313
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/400')
1294
1314
  stream.once('data', listenAtLogLine => {
1295
1315
  t.ok(listenAtLogLine, 'listen at log message is ok')
1296
1316
  stream.once('data', line => {
@@ -1313,7 +1333,7 @@ test('should log as error if error status code >= 500 if no error handler is def
1313
1333
  const stream = split(JSON.parse)
1314
1334
  const fastify = Fastify({
1315
1335
  logger: {
1316
- stream: stream,
1336
+ stream,
1317
1337
  level: 'info'
1318
1338
  }
1319
1339
  })
@@ -1321,10 +1341,10 @@ test('should log as error if error status code >= 500 if no error handler is def
1321
1341
  t.ok(req.log)
1322
1342
  reply.send(Object.assign(new Error('a 503 error'), { statusCode: 503 }))
1323
1343
  })
1324
- fastify.listen(0, err => {
1344
+ fastify.listen(0, localhost, err => {
1325
1345
  t.error(err)
1326
1346
  fastify.server.unref()
1327
- http.get('http://localhost:' + fastify.server.address().port + '/503')
1347
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/503')
1328
1348
  stream.once('data', listenAtLogLine => {
1329
1349
  t.ok(listenAtLogLine, 'listen at log message is ok')
1330
1350
  stream.once('data', line => {
@@ -1342,12 +1362,12 @@ test('should log as error if error status code >= 500 if no error handler is def
1342
1362
  })
1343
1363
  })
1344
1364
 
1345
- test('should not log the error if error handler is defined', t => {
1346
- t.plan(7)
1365
+ test('should not log the error if error handler is defined and it does not error', t => {
1366
+ t.plan(8)
1347
1367
  const stream = split(JSON.parse)
1348
1368
  const fastify = Fastify({
1349
1369
  logger: {
1350
- stream: stream,
1370
+ stream,
1351
1371
  level: 'info'
1352
1372
  }
1353
1373
  })
@@ -1356,12 +1376,13 @@ test('should not log the error if error handler is defined', t => {
1356
1376
  reply.send(new Error('something happened'))
1357
1377
  })
1358
1378
  fastify.setErrorHandler((err, req, reply) => {
1359
- reply.send(err)
1379
+ t.ok(err)
1380
+ reply.send('something bad happened')
1360
1381
  })
1361
- fastify.listen(0, err => {
1382
+ fastify.listen(0, localhost, err => {
1362
1383
  t.error(err)
1363
1384
  fastify.server.unref()
1364
- http.get('http://localhost:' + fastify.server.address().port + '/error')
1385
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/error')
1365
1386
  stream.once('data', listenAtLogLine => {
1366
1387
  t.ok(listenAtLogLine, 'listen at log message is ok')
1367
1388
  stream.once('data', line => {
@@ -1369,7 +1390,7 @@ test('should not log the error if error handler is defined', t => {
1369
1390
  stream.once('data', line => {
1370
1391
  t.equal(line.level, 30, 'level is correct')
1371
1392
  t.equal(line.msg, 'request completed', 'message is set')
1372
- t.same(line.res, { statusCode: 500 }, 'status code is set')
1393
+ t.same(line.res, { statusCode: 200 }, 'status code is set')
1373
1394
  })
1374
1395
  })
1375
1396
  })
@@ -1381,7 +1402,7 @@ test('should not rely on raw request to log errors', t => {
1381
1402
  const stream = split(JSON.parse)
1382
1403
  const fastify = Fastify({
1383
1404
  logger: {
1384
- stream: stream,
1405
+ stream,
1385
1406
  level: 'info'
1386
1407
  }
1387
1408
  })
@@ -1389,10 +1410,10 @@ test('should not rely on raw request to log errors', t => {
1389
1410
  t.ok(req.log)
1390
1411
  reply.status(415).send(new Error('something happened'))
1391
1412
  })
1392
- fastify.listen(0, err => {
1413
+ fastify.listen(0, localhost, err => {
1393
1414
  t.error(err)
1394
1415
  fastify.server.unref()
1395
- http.get('http://localhost:' + fastify.server.address().port + '/error')
1416
+ http.get(`http://${localhostForURL}:` + fastify.server.address().port + '/error')
1396
1417
  stream.once('data', listenAtLogLine => {
1397
1418
  t.ok(listenAtLogLine, 'listen at log message is ok')
1398
1419
  stream.once('data', line => {
@@ -1412,7 +1433,7 @@ test('should redact the authorization header if so specified', t => {
1412
1433
  const stream = split(JSON.parse)
1413
1434
  const fastify = Fastify({
1414
1435
  logger: {
1415
- stream: stream,
1436
+ stream,
1416
1437
  redact: ['req.headers.authorization'],
1417
1438
  level: 'info',
1418
1439
  serializers: {
@@ -1439,12 +1460,12 @@ test('should redact the authorization header if so specified', t => {
1439
1460
  t.equal(line.req.headers.authorization, '[Redacted]', 'authorization is redacted')
1440
1461
  })
1441
1462
  })
1442
- fastify.listen(0, err => {
1463
+ fastify.listen(0, localhost, err => {
1443
1464
  t.error(err)
1444
1465
  fastify.server.unref()
1445
1466
  sget({
1446
1467
  method: 'GET',
1447
- url: 'http://localhost:' + fastify.server.address().port,
1468
+ url: `http://${localhostForURL}:` + fastify.server.address().port,
1448
1469
  headers: {
1449
1470
  authorization: 'Bearer abcde'
1450
1471
  }
@@ -1481,6 +1502,25 @@ test('should not log incoming request and outgoing response when disabled', t =>
1481
1502
  })
1482
1503
  })
1483
1504
 
1505
+ test('should not log incoming request and outgoing response for 404 onBadUrl when disabled', t => {
1506
+ t.plan(1)
1507
+ const lines = []
1508
+ const dest = new stream.Writable({
1509
+ write: function (chunk, enc, cb) {
1510
+ lines.push(JSON.parse(chunk))
1511
+ cb()
1512
+ }
1513
+ })
1514
+ const fastify = Fastify({ disableRequestLogging: true, logger: { level: 'info', stream: dest } })
1515
+
1516
+ fastify.inject({
1517
+ url: '/%c0',
1518
+ method: 'GET'
1519
+ }, (e, res) => {
1520
+ t.same(lines.length, 0)
1521
+ })
1522
+ })
1523
+
1484
1524
  test('should pass when using unWritable props in the logger option', t => {
1485
1525
  t.plan(1)
1486
1526
  Fastify({
@@ -21,12 +21,12 @@ test('maxRequestsPerSocket on node version >= 16.10.0', { skip }, t => {
21
21
  t.error(err)
22
22
 
23
23
  const port = fastify.server.address().port
24
- const client = net.createConnection({ port: port }, () => {
24
+ const client = net.createConnection({ port }, () => {
25
25
  client.write('GET / HTTP/1.1\r\n\r\n')
26
26
 
27
27
  client.once('data', data => {
28
28
  t.match(data.toString(), /Connection:\s*keep-alive/i)
29
- t.match(data.toString(), /Keep-Alive:\s*timeout=5/i)
29
+ t.match(data.toString(), /Keep-Alive:\s*timeout=\d+/i)
30
30
  t.match(data.toString(), /200 OK/i)
31
31
 
32
32
  client.write('GET / HTTP/1.1\r\n\r\n')
@@ -40,6 +40,7 @@ test('maxRequestsPerSocket on node version >= 16.10.0', { skip }, t => {
40
40
  client.once('data', data => {
41
41
  t.match(data.toString(), /Connection:\s*close/i)
42
42
  t.match(data.toString(), /503 Service Unavailable/i)
43
+ client.end()
43
44
  })
44
45
  })
45
46
  })
@@ -61,27 +62,28 @@ test('maxRequestsPerSocket zero should behave same as null', { skip }, t => {
61
62
  t.error(err)
62
63
 
63
64
  const port = fastify.server.address().port
64
- const client = net.createConnection({ port: port }, () => {
65
+ const client = net.createConnection({ port }, () => {
65
66
  client.write('GET / HTTP/1.1\r\n\r\n')
66
67
 
67
68
  client.once('data', data => {
68
69
  t.match(data.toString(), /Connection:\s*keep-alive/i)
69
- t.match(data.toString(), /Keep-Alive:\s*timeout=5/i)
70
+ t.match(data.toString(), /Keep-Alive:\s*timeout=\d+/i)
70
71
  t.match(data.toString(), /200 OK/i)
71
72
 
72
73
  client.write('GET / HTTP/1.1\r\n\r\n')
73
74
 
74
75
  client.once('data', data => {
75
76
  t.match(data.toString(), /Connection:\s*keep-alive/i)
76
- t.match(data.toString(), /Keep-Alive:\s*timeout=5/i)
77
+ t.match(data.toString(), /Keep-Alive:\s*timeout=\d+/i)
77
78
  t.match(data.toString(), /200 OK/i)
78
79
 
79
80
  client.write('GET / HTTP/1.1\r\n\r\n')
80
81
 
81
82
  client.once('data', data => {
82
83
  t.match(data.toString(), /Connection:\s*keep-alive/i)
83
- t.match(data.toString(), /Keep-Alive:\s*timeout=5/i)
84
+ t.match(data.toString(), /Keep-Alive:\s*timeout=\d+/i)
84
85
  t.match(data.toString(), /200 OK/i)
86
+ client.end()
85
87
  })
86
88
  })
87
89
  })
@@ -3,22 +3,9 @@
3
3
  const { test } = require('tap')
4
4
  const Fastify = require('..')
5
5
  const {
6
- FST_ERR_DEC_ALREADY_PRESENT,
7
- FST_ERR_MISSING_MIDDLEWARE
6
+ FST_ERR_DEC_ALREADY_PRESENT
8
7
  } = require('../lib/errors')
9
8
 
10
- test('Should throw if the basic use API has not been overridden', t => {
11
- t.plan(1)
12
- const fastify = Fastify()
13
-
14
- try {
15
- fastify.use()
16
- t.fail('Should throw')
17
- } catch (err) {
18
- t.ok(err instanceof FST_ERR_MISSING_MIDDLEWARE)
19
- }
20
- })
21
-
22
9
  test('Should be able to override the default use API', t => {
23
10
  t.plan(1)
24
11
  const fastify = Fastify()
@@ -38,7 +25,7 @@ test('Cannot decorate use twice', t => {
38
25
  })
39
26
 
40
27
  test('Encapsulation works', t => {
41
- t.plan(2)
28
+ t.plan(1)
42
29
  const fastify = Fastify()
43
30
 
44
31
  fastify.register((instance, opts, done) => {
@@ -47,15 +34,5 @@ test('Encapsulation works', t => {
47
34
  done()
48
35
  })
49
36
 
50
- fastify.register((instance, opts, done) => {
51
- try {
52
- instance.use()
53
- t.fail('Should throw')
54
- } catch (err) {
55
- t.ok(err instanceof FST_ERR_MISSING_MIDDLEWARE)
56
- }
57
- done()
58
- })
59
-
60
37
  fastify.ready()
61
38
  })
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const tap = require('tap')
4
+ const noopSet = require('../lib/noop-set')
5
+
6
+ tap.test('does a lot of nothing', async t => {
7
+ const aSet = noopSet()
8
+ t.type(aSet, 'object')
9
+
10
+ const item = {}
11
+ aSet.add(item)
12
+ aSet.add({ another: 'item' })
13
+ aSet.delete(item)
14
+ t.equal(aSet.has(item), true)
15
+
16
+ for (const i of aSet) {
17
+ t.fail('should not have any items', i)
18
+ }
19
+ })
@@ -61,8 +61,8 @@ test('object or null body', t => {
61
61
  method: 'POST',
62
62
  url: '/',
63
63
  handler: (req, reply) => {
64
- t.equal(req.body, null)
65
- reply.code(200).send({ requestBody: req.body })
64
+ t.equal(req.body, undefined)
65
+ reply.code(200).send({ isUndefinedBody: req.body === undefined })
66
66
  },
67
67
  schema: {
68
68
  body: {
@@ -79,10 +79,8 @@ test('object or null body', t => {
79
79
  type: 'object',
80
80
  nullable: true,
81
81
  properties: {
82
- requestBody: {
83
- type: 'string',
84
- format: 'email',
85
- nullable: true
82
+ isUndefinedBody: {
83
+ type: 'boolean'
86
84
  }
87
85
  }
88
86
  }
@@ -100,7 +98,7 @@ test('object or null body', t => {
100
98
  }, (err, response, body) => {
101
99
  t.error(err)
102
100
  t.equal(response.statusCode, 200)
103
- t.same(JSON.parse(body), { requestBody: null })
101
+ t.same(JSON.parse(body), { isUndefinedBody: true })
104
102
  })
105
103
  })
106
104
  })
@@ -114,8 +112,8 @@ test('nullable body', t => {
114
112
  method: 'POST',
115
113
  url: '/',
116
114
  handler: (req, reply) => {
117
- t.equal(req.body, null)
118
- reply.code(200).send({ requestBody: req.body })
115
+ t.equal(req.body, undefined)
116
+ reply.code(200).send({ isUndefinedBody: req.body === undefined })
119
117
  },
120
118
  schema: {
121
119
  body: {
@@ -133,10 +131,8 @@ test('nullable body', t => {
133
131
  type: 'object',
134
132
  nullable: true,
135
133
  properties: {
136
- requestBody: {
137
- type: 'string',
138
- format: 'email',
139
- nullable: true
134
+ isUndefinedBody: {
135
+ type: 'boolean'
140
136
  }
141
137
  }
142
138
  }
@@ -154,7 +150,48 @@ test('nullable body', t => {
154
150
  }, (err, response, body) => {
155
151
  t.error(err)
156
152
  t.equal(response.statusCode, 200)
157
- t.same(JSON.parse(body), { requestBody: null })
153
+ t.same(JSON.parse(body), { isUndefinedBody: true })
154
+ })
155
+ })
156
+ })
157
+
158
+ test('Nullable body with 204', t => {
159
+ t.plan(5)
160
+
161
+ const fastify = Fastify()
162
+
163
+ fastify.route({
164
+ method: 'POST',
165
+ url: '/',
166
+ handler: (req, reply) => {
167
+ t.equal(req.body, undefined)
168
+ reply.code(204).send()
169
+ },
170
+ schema: {
171
+ body: {
172
+ type: 'object',
173
+ nullable: true,
174
+ properties: {
175
+ hello: {
176
+ type: 'string',
177
+ format: 'email'
178
+ }
179
+ }
180
+ }
181
+ }
182
+ })
183
+
184
+ fastify.listen(0, (err) => {
185
+ fastify.server.unref()
186
+ t.error(err)
187
+
188
+ sget({
189
+ method: 'POST',
190
+ url: 'http://localhost:' + fastify.server.address().port
191
+ }, (err, response, body) => {
192
+ t.error(err)
193
+ t.equal(response.statusCode, 204)
194
+ t.equal(body.length, 0)
158
195
  })
159
196
  })
160
197
  })