fastify 3.27.3 → 4.0.0-alpha.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.
Files changed (164) hide show
  1. package/.taprc +3 -0
  2. package/README.md +7 -7
  3. package/build/build-error-serializer.js +27 -0
  4. package/build/build-validation.js +47 -35
  5. package/docs/Guides/Database.md +320 -0
  6. package/docs/Guides/Getting-Started.md +7 -7
  7. package/docs/Guides/Plugins-Guide.md +1 -1
  8. package/docs/Guides/Serverless.md +3 -3
  9. package/docs/Guides/Testing.md +2 -2
  10. package/docs/Migration-Guide-V4.md +12 -0
  11. package/docs/Reference/ContentTypeParser.md +4 -0
  12. package/docs/Reference/Decorators.md +2 -2
  13. package/docs/Reference/Encapsulation.md +2 -2
  14. package/docs/Reference/Errors.md +51 -6
  15. package/docs/Reference/HTTP2.md +3 -3
  16. package/docs/Reference/Hooks.md +4 -7
  17. package/docs/Reference/LTS.md +5 -4
  18. package/docs/Reference/Plugins.md +3 -3
  19. package/docs/Reference/Reply.md +23 -22
  20. package/docs/Reference/Request.md +1 -3
  21. package/docs/Reference/Routes.md +22 -15
  22. package/docs/Reference/Server.md +69 -119
  23. package/docs/Reference/TypeScript.md +20 -22
  24. package/docs/Reference/Validation-and-Serialization.md +30 -55
  25. package/docs/Type-Providers.md +257 -0
  26. package/examples/asyncawait.js +1 -1
  27. package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
  28. package/examples/benchmark/hooks-benchmark.js +1 -1
  29. package/examples/benchmark/simple.js +1 -1
  30. package/examples/hooks.js +2 -2
  31. package/examples/http2.js +1 -1
  32. package/examples/https.js +1 -1
  33. package/examples/parser.js +1 -1
  34. package/examples/route-prefix.js +1 -1
  35. package/examples/shared-schema.js +1 -1
  36. package/examples/simple-stream.js +18 -0
  37. package/examples/simple.js +1 -1
  38. package/examples/simple.mjs +1 -1
  39. package/examples/typescript-server.ts +1 -1
  40. package/examples/use-plugin.js +1 -1
  41. package/fastify.d.ts +34 -22
  42. package/fastify.js +40 -36
  43. package/lib/configValidator.js +902 -1023
  44. package/lib/contentTypeParser.js +6 -16
  45. package/lib/context.js +36 -10
  46. package/lib/decorate.js +3 -1
  47. package/lib/error-handler.js +158 -0
  48. package/lib/error-serializer.js +257 -0
  49. package/lib/errors.js +43 -9
  50. package/lib/fourOhFour.js +31 -20
  51. package/lib/handleRequest.js +10 -13
  52. package/lib/hooks.js +14 -9
  53. package/lib/pluginOverride.js +0 -3
  54. package/lib/pluginUtils.js +3 -2
  55. package/lib/reply.js +29 -158
  56. package/lib/request.js +13 -10
  57. package/lib/route.js +131 -138
  58. package/lib/schema-controller.js +2 -2
  59. package/lib/schemas.js +27 -1
  60. package/lib/server.js +241 -116
  61. package/lib/symbols.js +4 -3
  62. package/lib/validation.js +2 -1
  63. package/lib/warnings.js +4 -12
  64. package/lib/wrapThenable.js +4 -11
  65. package/package.json +37 -39
  66. package/test/404s.test.js +258 -125
  67. package/test/500s.test.js +3 -3
  68. package/test/als.test.js +1 -1
  69. package/test/async-await.test.js +20 -76
  70. package/test/bodyLimit.test.js +1 -1
  71. package/test/build-certificate.js +6 -7
  72. package/test/case-insensitive.test.js +4 -4
  73. package/test/close-pipelining.test.js +2 -2
  74. package/test/close.test.js +11 -11
  75. package/test/content-parser.test.js +32 -0
  76. package/test/context-config.test.js +52 -0
  77. package/test/custom-http-server.test.js +14 -7
  78. package/test/custom-parser-async.test.js +1 -66
  79. package/test/custom-parser.test.js +92 -159
  80. package/test/custom-querystring-parser.test.js +3 -3
  81. package/test/decorator.test.js +11 -13
  82. package/test/delete.test.js +6 -6
  83. package/test/encapsulated-error-handler.test.js +50 -0
  84. package/test/esm/index.test.js +0 -14
  85. package/test/fastify-instance.test.js +4 -4
  86. package/test/fluent-schema.test.js +4 -4
  87. package/test/genReqId.test.js +1 -1
  88. package/test/get.test.js +4 -4
  89. package/test/handler-context.test.js +2 -2
  90. package/test/head.test.js +1 -1
  91. package/test/helper.js +19 -4
  92. package/test/hooks-async.test.js +15 -48
  93. package/test/hooks.on-ready.test.js +10 -5
  94. package/test/hooks.test.js +78 -119
  95. package/test/http2/closing.test.js +10 -16
  96. package/test/http2/constraint.test.js +1 -1
  97. package/test/http2/head.test.js +1 -1
  98. package/test/http2/plain.test.js +1 -1
  99. package/test/http2/secure-with-fallback.test.js +1 -1
  100. package/test/http2/secure.test.js +1 -1
  101. package/test/http2/unknown-http-method.test.js +4 -10
  102. package/test/https/custom-https-server.test.js +12 -6
  103. package/test/https/https.test.js +1 -1
  104. package/test/input-validation.js +3 -3
  105. package/test/internals/handleRequest.test.js +6 -43
  106. package/test/internals/initialConfig.test.js +41 -12
  107. package/test/internals/logger.test.js +2 -2
  108. package/test/internals/reply.test.js +281 -40
  109. package/test/internals/request.test.js +13 -7
  110. package/test/internals/server.test.js +88 -0
  111. package/test/listen.deprecated.test.js +202 -0
  112. package/test/listen.test.js +118 -150
  113. package/test/logger.test.js +82 -42
  114. package/test/maxRequestsPerSocket.test.js +8 -6
  115. package/test/middleware.test.js +2 -25
  116. package/test/nullable-validation.test.js +53 -16
  117. package/test/output-validation.test.js +1 -1
  118. package/test/plugin.test.js +47 -21
  119. package/test/pretty-print.test.js +22 -10
  120. package/test/promises.test.js +1 -1
  121. package/test/proto-poisoning.test.js +6 -6
  122. package/test/register.test.js +3 -3
  123. package/test/reply-error.test.js +126 -15
  124. package/test/request-error.test.js +3 -6
  125. package/test/route-hooks.test.js +18 -18
  126. package/test/route-prefix.test.js +2 -1
  127. package/test/route.test.js +206 -22
  128. package/test/router-options.test.js +2 -2
  129. package/test/schema-examples.test.js +11 -5
  130. package/test/schema-feature.test.js +25 -20
  131. package/test/schema-serialization.test.js +9 -9
  132. package/test/schema-special-usage.test.js +5 -153
  133. package/test/schema-validation.test.js +9 -9
  134. package/test/skip-reply-send.test.js +2 -2
  135. package/test/stream.test.js +82 -23
  136. package/test/throw.test.js +8 -5
  137. package/test/trust-proxy.test.js +6 -6
  138. package/test/type-provider.test.js +20 -0
  139. package/test/types/fastify.test-d.ts +10 -18
  140. package/test/types/import.js +2 -0
  141. package/test/types/import.ts +1 -0
  142. package/test/types/instance.test-d.ts +68 -17
  143. package/test/types/logger.test-d.ts +44 -15
  144. package/test/types/reply.test-d.ts +2 -1
  145. package/test/types/route.test-d.ts +8 -2
  146. package/test/types/schema.test-d.ts +2 -39
  147. package/test/types/type-provider.test-d.ts +417 -0
  148. package/test/url-rewriting.test.js +3 -3
  149. package/test/validation-error-handling.test.js +8 -8
  150. package/test/versioned-routes.test.js +30 -18
  151. package/test/wrapThenable.test.js +7 -6
  152. package/types/content-type-parser.d.ts +17 -8
  153. package/types/hooks.d.ts +102 -59
  154. package/types/instance.d.ts +244 -118
  155. package/types/logger.d.ts +18 -104
  156. package/types/plugin.d.ts +10 -4
  157. package/types/reply.d.ts +18 -12
  158. package/types/request.d.ts +10 -5
  159. package/types/route.d.ts +42 -31
  160. package/types/schema.d.ts +1 -1
  161. package/types/type-provider.d.ts +99 -0
  162. package/types/utils.d.ts +1 -1
  163. package/lib/schema-compilers.js +0 -12
  164. 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,7 +39,6 @@ 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 {
@@ -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({ port: 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
54
66
 
67
+ function skip (data) {
68
+ if (--toSkip === 0) {
69
+ stream.removeListener('data', skip)
70
+ check()
71
+ }
72
+ }
73
+
74
+ stream.on('data', skip)
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 => {
@@ -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({ port: 0, host: 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
 
@@ -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({ port: 0, host: 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
 
@@ -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({ port: 0, host: 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()
@@ -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({ port: 0, host: 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()
@@ -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({ port: 0, host: 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
 
@@ -1155,7 +1175,7 @@ test('should serialize request and response', t => {
1155
1175
  level: 'info'
1156
1176
  }
1157
1177
  })
1158
- fastify.listen(0, ipv6, err => {
1178
+ fastify.listen({ port: 0, host: ipv6 }, err => {
1159
1179
  t.error(err)
1160
1180
  stream.once('data', line => {
1161
1181
  const expected = 'Server listening at http://[' + ipv6 + ']:' +
@@ -1177,7 +1197,7 @@ test('Do not wrap IPv4 address', t => {
1177
1197
  level: 'info'
1178
1198
  }
1179
1199
  })
1180
- fastify.listen(0, '127.0.0.1', err => {
1200
+ fastify.listen({ port: 0, host: '127.0.0.1' }, err => {
1181
1201
  t.error(err)
1182
1202
  stream.once('data', line => {
1183
1203
  const expected = 'Server listening at http://127.0.0.1:' +
@@ -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({ port: 0, host: 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 => {
@@ -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({ port: 0, host: 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 => {
@@ -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({ port: 0, host: 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 => {
@@ -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({ port: 0, host: 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,8 +1362,8 @@ 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: {
@@ -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({ port: 0, host: 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
  })
@@ -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({ port: 0, host: 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 => {
@@ -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({ port: 0, host: 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({
@@ -17,7 +17,7 @@ test('maxRequestsPerSocket on node version >= 16.10.0', { skip }, t => {
17
17
 
18
18
  t.teardown(fastify.close.bind(fastify))
19
19
 
20
- fastify.listen(0, function (err) {
20
+ fastify.listen({ port: 0 }, function (err) {
21
21
  t.error(err)
22
22
 
23
23
  const port = fastify.server.address().port
@@ -26,7 +26,7 @@ test('maxRequestsPerSocket on node version >= 16.10.0', { skip }, t => {
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
  })
@@ -57,7 +58,7 @@ test('maxRequestsPerSocket zero should behave same as null', { skip }, t => {
57
58
 
58
59
  t.teardown(fastify.close.bind(fastify))
59
60
 
60
- fastify.listen(0, function (err) {
61
+ fastify.listen({ port: 0 }, function (err) {
61
62
  t.error(err)
62
63
 
63
64
  const port = fastify.server.address().port
@@ -66,22 +67,23 @@ test('maxRequestsPerSocket zero should behave same as null', { skip }, t => {
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
  })
@@ -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
  }
@@ -90,7 +88,7 @@ test('object or null body', t => {
90
88
  }
91
89
  })
92
90
 
93
- fastify.listen(0, (err) => {
91
+ fastify.listen({ port: 0 }, (err) => {
94
92
  fastify.server.unref()
95
93
  t.error(err)
96
94
 
@@ -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
  }
@@ -144,7 +140,7 @@ test('nullable body', t => {
144
140
  }
145
141
  })
146
142
 
147
- fastify.listen(0, (err) => {
143
+ fastify.listen({ port: 0 }, (err) => {
148
144
  fastify.server.unref()
149
145
  t.error(err)
150
146
 
@@ -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({ port: 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
  })
@@ -90,7 +90,7 @@ test('unlisted response code', t => {
90
90
  }
91
91
  })
92
92
 
93
- fastify.listen(0, err => {
93
+ fastify.listen({ port: 0 }, err => {
94
94
  t.error(err)
95
95
  fastify.server.unref()
96
96