fastify 3.24.0 → 3.25.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 (67) hide show
  1. package/README.md +30 -29
  2. package/docs/{Benchmarking.md → Guides/Benchmarking.md} +14 -5
  3. package/docs/Guides/Ecosystem.md +513 -0
  4. package/docs/{Fluent-Schema.md → Guides/Fluent-Schema.md} +16 -7
  5. package/docs/{Getting-Started.md → Guides/Getting-Started.md} +180 -60
  6. package/docs/Guides/Index.md +30 -4
  7. package/docs/{Migration-Guide-V3.md → Guides/Migration-Guide-V3.md} +43 -37
  8. package/docs/{Plugins-Guide.md → Guides/Plugins-Guide.md} +196 -82
  9. package/docs/{Recommendations.md → Guides/Recommendations.md} +17 -10
  10. package/docs/{Serverless.md → Guides/Serverless.md} +200 -42
  11. package/docs/Guides/Style-Guide.md +246 -0
  12. package/docs/{Testing.md → Guides/Testing.md} +26 -12
  13. package/docs/Guides/Write-Plugin.md +102 -0
  14. package/docs/{ContentTypeParser.md → Reference/ContentTypeParser.md} +68 -30
  15. package/docs/{Decorators.md → Reference/Decorators.md} +52 -47
  16. package/docs/{Encapsulation.md → Reference/Encapsulation.md} +3 -3
  17. package/docs/{Errors.md → Reference/Errors.md} +77 -47
  18. package/docs/{HTTP2.md → Reference/HTTP2.md} +13 -13
  19. package/docs/{Hooks.md → Reference/Hooks.md} +157 -70
  20. package/docs/Reference/Index.md +71 -0
  21. package/docs/{LTS.md → Reference/LTS.md} +31 -32
  22. package/docs/{Lifecycle.md → Reference/Lifecycle.md} +15 -7
  23. package/docs/{Logging.md → Reference/Logging.md} +68 -28
  24. package/docs/Reference/Middleware.md +78 -0
  25. package/docs/{Plugins.md → Reference/Plugins.md} +91 -34
  26. package/docs/{Reply.md → Reference/Reply.md} +205 -94
  27. package/docs/{Request.md → Reference/Request.md} +32 -16
  28. package/docs/{Routes.md → Reference/Routes.md} +243 -113
  29. package/docs/{Server.md → Reference/Server.md} +516 -267
  30. package/docs/{TypeScript.md → Reference/TypeScript.md} +451 -191
  31. package/docs/{Validation-and-Serialization.md → Reference/Validation-and-Serialization.md} +178 -86
  32. package/docs/index.md +24 -0
  33. package/examples/typescript-server.ts +1 -1
  34. package/fastify.js +2 -3
  35. package/lib/contentTypeParser.js +11 -6
  36. package/lib/decorate.js +6 -3
  37. package/lib/logger.js +1 -1
  38. package/lib/route.js +1 -1
  39. package/lib/server.js +9 -8
  40. package/package.json +9 -4
  41. package/test/als.test.js +74 -0
  42. package/test/constrained-routes.test.js +220 -0
  43. package/test/custom-parser.test.js +11 -2
  44. package/test/decorator.test.js +38 -0
  45. package/test/handler-context.test.js +11 -4
  46. package/test/http2/closing.test.js +14 -5
  47. package/test/http2/constraint.test.js +91 -0
  48. package/test/listen.test.js +36 -22
  49. package/test/logger.test.js +16 -0
  50. package/test/maxRequestsPerSocket.test.js +10 -0
  51. package/test/request-error.test.js +2 -8
  52. package/test/requestTimeout.test.js +4 -1
  53. package/test/router-options.test.js +10 -1
  54. package/test/schema-feature.test.js +146 -0
  55. package/test/stream.test.js +14 -3
  56. package/test/trust-proxy.test.js +15 -7
  57. package/test/types/instance.test-d.ts +52 -1
  58. package/test/types/request.test-d.ts +7 -1
  59. package/test/types/route.test-d.ts +21 -0
  60. package/types/hooks.d.ts +12 -1
  61. package/types/instance.d.ts +16 -6
  62. package/types/request.d.ts +4 -1
  63. package/types/route.d.ts +1 -1
  64. package/docs/Ecosystem.md +0 -211
  65. package/docs/Middleware.md +0 -53
  66. package/docs/Style-Guide.md +0 -185
  67. package/docs/Write-Plugin.md +0 -58
@@ -3,15 +3,29 @@
3
3
  const os = require('os')
4
4
  const path = require('path')
5
5
  const fs = require('fs')
6
- const test = require('tap').test
6
+ const { test, before } = require('tap')
7
7
  const Fastify = require('..')
8
+ const dns = require('dns').promises
9
+
10
+ let localhost
11
+ let localhostForURL
12
+
13
+ before(async function () {
14
+ const lookup = await dns.lookup('localhost')
15
+ localhost = lookup.address
16
+ if (lookup.family === 6) {
17
+ localhostForURL = `[${lookup.address}]`
18
+ } else {
19
+ localhostForURL = localhost
20
+ }
21
+ })
8
22
 
9
23
  test('listen accepts a callback', t => {
10
24
  t.plan(2)
11
25
  const fastify = Fastify()
12
26
  t.teardown(fastify.close.bind(fastify))
13
27
  fastify.listen((err) => {
14
- t.equal(fastify.server.address().address, '127.0.0.1')
28
+ t.equal(fastify.server.address().address, localhost)
15
29
  t.error(err)
16
30
  })
17
31
  })
@@ -21,7 +35,7 @@ test('listen accepts a port and a callback', t => {
21
35
  const fastify = Fastify()
22
36
  t.teardown(fastify.close.bind(fastify))
23
37
  fastify.listen(0, (err) => {
24
- t.equal(fastify.server.address().address, '127.0.0.1')
38
+ t.equal(fastify.server.address().address, localhost)
25
39
  t.error(err)
26
40
  })
27
41
  })
@@ -31,7 +45,7 @@ test('listen accepts a port and a callback with (err, address)', t => {
31
45
  const fastify = Fastify()
32
46
  t.teardown(fastify.close.bind(fastify))
33
47
  fastify.listen(0, (err, address) => {
34
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
48
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
35
49
  t.error(err)
36
50
  })
37
51
  })
@@ -40,7 +54,7 @@ test('listen accepts a port, address, and callback', t => {
40
54
  t.plan(1)
41
55
  const fastify = Fastify()
42
56
  t.teardown(fastify.close.bind(fastify))
43
- fastify.listen(0, '127.0.0.1', (err) => {
57
+ fastify.listen(0, localhost, (err) => {
44
58
  t.error(err)
45
59
  })
46
60
  })
@@ -78,8 +92,8 @@ test('listen accepts a port, address and a callback with (err, address)', t => {
78
92
  t.plan(2)
79
93
  const fastify = Fastify()
80
94
  t.teardown(fastify.close.bind(fastify))
81
- fastify.listen(0, '127.0.0.1', (err, address) => {
82
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
95
+ fastify.listen(0, localhost, (err, address) => {
96
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
83
97
  t.error(err)
84
98
  })
85
99
  })
@@ -88,7 +102,7 @@ test('listen accepts a port, address, backlog and callback', t => {
88
102
  t.plan(1)
89
103
  const fastify = Fastify()
90
104
  t.teardown(fastify.close.bind(fastify))
91
- fastify.listen(0, '127.0.0.1', 511, (err) => {
105
+ fastify.listen(0, localhost, 511, (err) => {
92
106
  t.error(err)
93
107
  })
94
108
  })
@@ -97,8 +111,8 @@ test('listen accepts a port, address, backlog and callback with (err, address)',
97
111
  t.plan(2)
98
112
  const fastify = Fastify()
99
113
  t.teardown(fastify.close.bind(fastify))
100
- fastify.listen(0, '127.0.0.1', 511, (err, address) => {
101
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
114
+ fastify.listen(0, localhost, 511, (err, address) => {
115
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
102
116
  t.error(err)
103
117
  })
104
118
  })
@@ -111,7 +125,7 @@ test('listen after Promise.resolve()', t => {
111
125
  .then(() => {
112
126
  f.listen(0, (err, address) => {
113
127
  f.server.unref()
114
- t.equal(address, 'http://127.0.0.1:' + f.server.address().port)
128
+ t.equal(address, `http://${localhostForURL}:${f.server.address().port}`)
115
129
  t.error(err)
116
130
  })
117
131
  })
@@ -153,7 +167,7 @@ test('double listen errors callback with (err, address)', t => {
153
167
  const fastify = Fastify()
154
168
  t.teardown(fastify.close.bind(fastify))
155
169
  fastify.listen(0, (err1, address1) => {
156
- t.equal(address1, 'http://127.0.0.1:' + fastify.server.address().port)
170
+ t.equal(address1, `http://${localhostForURL}:${fastify.server.address().port}`)
157
171
  t.error(err1)
158
172
  fastify.listen(fastify.server.address().port, (err2, address2) => {
159
173
  t.equal(address2, null)
@@ -167,7 +181,7 @@ test('listen twice on the same port', t => {
167
181
  const fastify = Fastify()
168
182
  t.teardown(fastify.close.bind(fastify))
169
183
  fastify.listen(0, (err1, address1) => {
170
- t.equal(address1, 'http://127.0.0.1:' + fastify.server.address().port)
184
+ t.equal(address1, `http://${localhostForURL}:${fastify.server.address().port}`)
171
185
  t.error(err1)
172
186
  const s2 = Fastify()
173
187
  t.teardown(s2.close.bind(s2))
@@ -184,7 +198,7 @@ test('listen twice on the same port callback with (err, address)', t => {
184
198
  t.teardown(fastify.close.bind(fastify))
185
199
  fastify.listen(0, (err1, address1) => {
186
200
  const _port = fastify.server.address().port
187
- t.equal(address1, 'http://127.0.0.1:' + _port)
201
+ t.equal(address1, `http://${localhostForURL}:${_port}`)
188
202
  t.error(err1)
189
203
  const s2 = Fastify()
190
204
  t.teardown(s2.close.bind(s2))
@@ -221,7 +235,7 @@ test('listen without callback (port zero)', t => {
221
235
  t.teardown(fastify.close.bind(fastify))
222
236
  fastify.listen(0)
223
237
  .then(() => {
224
- t.equal(fastify.server.address().address, '127.0.0.1')
238
+ t.equal(fastify.server.address().address, localhost)
225
239
  })
226
240
  })
227
241
 
@@ -231,7 +245,7 @@ test('listen without callback (port not given)', t => {
231
245
  t.teardown(fastify.close.bind(fastify))
232
246
  fastify.listen()
233
247
  .then(() => {
234
- t.equal(fastify.server.address().address, '127.0.0.1')
248
+ t.equal(fastify.server.address().address, localhost)
235
249
  })
236
250
  })
237
251
 
@@ -241,7 +255,7 @@ test('listen null without callback with (address)', t => {
241
255
  t.teardown(fastify.close.bind(fastify))
242
256
  fastify.listen(null)
243
257
  .then(address => {
244
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
258
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
245
259
  })
246
260
  })
247
261
 
@@ -251,7 +265,7 @@ test('listen without port without callback with (address)', t => {
251
265
  t.teardown(fastify.close.bind(fastify))
252
266
  fastify.listen()
253
267
  .then(address => {
254
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
268
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
255
269
  })
256
270
  })
257
271
 
@@ -261,7 +275,7 @@ test('listen with undefined without callback with (address)', t => {
261
275
  t.teardown(fastify.close.bind(fastify))
262
276
  fastify.listen(undefined)
263
277
  .then(address => {
264
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
278
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
265
279
  })
266
280
  })
267
281
 
@@ -271,7 +285,7 @@ test('listen without callback with (address)', t => {
271
285
  t.teardown(fastify.close.bind(fastify))
272
286
  fastify.listen(0)
273
287
  .then(address => {
274
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
288
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
275
289
  })
276
290
  })
277
291
 
@@ -295,7 +309,7 @@ test('double listen without callback with (address)', t => {
295
309
  t.teardown(fastify.close.bind(fastify))
296
310
  fastify.listen(0)
297
311
  .then(address => {
298
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
312
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
299
313
  fastify.listen(0)
300
314
  .catch(err => {
301
315
  t.ok(err)
@@ -329,7 +343,7 @@ test('listen twice on the same port without callback rejects with (address)', t
329
343
  .then(address => {
330
344
  const s2 = Fastify()
331
345
  t.teardown(s2.close.bind(s2))
332
- t.equal(address, 'http://127.0.0.1:' + fastify.server.address().port)
346
+ t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
333
347
  s2.listen(fastify.server.address().port)
334
348
  .catch(err => {
335
349
  t.ok(err)
@@ -1516,3 +1516,19 @@ test('should create a default logger if provided one is invalid', t => {
1516
1516
 
1517
1517
  t.pass()
1518
1518
  })
1519
+
1520
+ test('should not throw error when serializing custom req', t => {
1521
+ t.plan(1)
1522
+
1523
+ const lines = []
1524
+ const dest = new stream.Writable({
1525
+ write: function (chunk, enc, cb) {
1526
+ lines.push(JSON.parse(chunk))
1527
+ cb()
1528
+ }
1529
+ })
1530
+ const fastify = Fastify({ logger: { level: 'info', stream: dest } })
1531
+ fastify.log.info({ req: {} })
1532
+
1533
+ t.same(lines[0].req, {})
1534
+ })
@@ -102,3 +102,13 @@ test('maxRequestsPerSocket should 0', async (t) => {
102
102
  const initialConfig = Fastify().initialConfig
103
103
  t.same(initialConfig.maxRequestsPerSocket, 0)
104
104
  })
105
+
106
+ test('requestTimeout passed to server', t => {
107
+ t.plan(2)
108
+
109
+ const httpServer = Fastify({ maxRequestsPerSocket: 5 }).server
110
+ t.equal(httpServer.maxRequestsPerSocket, 5)
111
+
112
+ const httpsServer = Fastify({ maxRequestsPerSocket: 5, https: true }).server
113
+ t.equal(httpsServer.maxRequestsPerSocket, 5)
114
+ })
@@ -157,10 +157,7 @@ test('default clientError handler destroys sockets in writable state', t => {
157
157
 
158
158
  const fastify = Fastify({
159
159
  bodyLimit: 1,
160
- keepAliveTimeout: 100,
161
- logger: {
162
- level: 'trace'
163
- }
160
+ keepAliveTimeout: 100
164
161
  })
165
162
 
166
163
  fastify.server.emit('clientError', new Error(), {
@@ -181,10 +178,7 @@ test('default clientError handler destroys http sockets in non-writable state',
181
178
 
182
179
  const fastify = Fastify({
183
180
  bodyLimit: 1,
184
- keepAliveTimeout: 100,
185
- logger: {
186
- level: 'trace'
187
- }
181
+ keepAliveTimeout: 100
188
182
  })
189
183
 
190
184
  fastify.server.emit('clientError', new Error(), {
@@ -5,7 +5,7 @@ const { test } = require('tap')
5
5
  const Fastify = require('../fastify')
6
6
 
7
7
  test('requestTimeout passed to server', t => {
8
- t.plan(4)
8
+ t.plan(5)
9
9
 
10
10
  try {
11
11
  Fastify({ requestTimeout: 500.1 })
@@ -24,6 +24,9 @@ test('requestTimeout passed to server', t => {
24
24
  const httpServer = Fastify({ requestTimeout: 1000 }).server
25
25
  t.equal(httpServer.requestTimeout, 1000)
26
26
 
27
+ const httpsServer = Fastify({ requestTimeout: 1000, https: true }).server
28
+ t.equal(httpsServer.requestTimeout, 1000)
29
+
27
30
  const serverFactory = (handler, _) => {
28
31
  const server = http.createServer((req, res) => {
29
32
  handler(req, res)
@@ -5,6 +5,15 @@ const sget = require('simple-get')
5
5
  const Fastify = require('../')
6
6
  const { FST_ERR_BAD_URL } = require('../lib/errors')
7
7
 
8
+ function getUrl (app) {
9
+ const { address, port } = app.server.address()
10
+ if (address === '::1') {
11
+ return `http://[${address}]:${port}`
12
+ } else {
13
+ return `http://${address}:${port}`
14
+ }
15
+ }
16
+
8
17
  test('Should honor ignoreTrailingSlash option', t => {
9
18
  t.plan(4)
10
19
  const fastify = Fastify({
@@ -19,7 +28,7 @@ test('Should honor ignoreTrailingSlash option', t => {
19
28
  fastify.server.unref()
20
29
  if (err) t.threw(err)
21
30
 
22
- const baseUrl = 'http://127.0.0.1:' + fastify.server.address().port
31
+ const baseUrl = getUrl(fastify)
23
32
 
24
33
  sget.concat(baseUrl + '/test', (err, res, data) => {
25
34
  if (err) t.threw(err)
@@ -1604,3 +1604,149 @@ test('setSchemaController: Inherits buildValidator from parent if not present wi
1604
1604
  t.equal(childSerializerCalled, 1, 'Should be called from the child')
1605
1605
  t.equal(res.statusCode, 400, 'Should not coearce the string into array')
1606
1606
  })
1607
+
1608
+ test('Should throw if not default validator passed', async t => {
1609
+ t.plan(4)
1610
+ const customAjv = new Ajv({ coerceTypes: false })
1611
+ const someSchema = {
1612
+ $id: 'some',
1613
+ type: 'array',
1614
+ items: {
1615
+ type: 'string'
1616
+ }
1617
+ }
1618
+ const anotherSchema = {
1619
+ $id: 'another',
1620
+ type: 'integer'
1621
+ }
1622
+ const plugin = fp(function (pluginInstance, _, pluginDone) {
1623
+ pluginInstance.setSchemaController({
1624
+ compilersFactory: {
1625
+ buildValidator: function (externalSchemas) {
1626
+ const schemaKeys = Object.keys(externalSchemas)
1627
+ t.equal(schemaKeys.length, 2)
1628
+ t.same(schemaKeys, ['some', 'another'])
1629
+
1630
+ for (const key of schemaKeys) {
1631
+ if (customAjv.getSchema(key) == null) {
1632
+ customAjv.addSchema(externalSchemas[key], key)
1633
+ }
1634
+ }
1635
+ return function validatorCompiler ({ schema }) {
1636
+ return customAjv.compile(schema)
1637
+ }
1638
+ }
1639
+ }
1640
+ })
1641
+
1642
+ pluginDone()
1643
+ })
1644
+ const server = Fastify()
1645
+
1646
+ server.addSchema(someSchema)
1647
+
1648
+ server.register((instance, opts, done) => {
1649
+ instance.addSchema(anotherSchema)
1650
+
1651
+ instance.register(plugin, {})
1652
+
1653
+ instance.post(
1654
+ '/',
1655
+ {
1656
+ schema: {
1657
+ query: {
1658
+ msg: {
1659
+ $ref: 'some#'
1660
+ }
1661
+ },
1662
+ headers: {
1663
+ 'x-another': {
1664
+ $ref: 'another#'
1665
+ }
1666
+ }
1667
+ }
1668
+ },
1669
+ (req, reply) => {
1670
+ reply.send({ noop: 'noop' })
1671
+ }
1672
+ )
1673
+
1674
+ done()
1675
+ })
1676
+
1677
+ try {
1678
+ const res = await server.inject({
1679
+ method: 'POST',
1680
+ url: '/',
1681
+ query: {
1682
+ msg: ['string']
1683
+ }
1684
+ })
1685
+
1686
+ t.equal(res.json().message, 'querystring.msg should be array')
1687
+ t.equal(res.statusCode, 400, 'Should not coearce the string into array')
1688
+ } catch (err) {
1689
+ t.error(err)
1690
+ }
1691
+ })
1692
+
1693
+ test('Should throw if not default validator passed', async t => {
1694
+ t.plan(2)
1695
+ const someSchema = {
1696
+ $id: 'some',
1697
+ type: 'array',
1698
+ items: {
1699
+ type: 'string'
1700
+ }
1701
+ }
1702
+ const anotherSchema = {
1703
+ $id: 'another',
1704
+ type: 'integer'
1705
+ }
1706
+
1707
+ const server = Fastify()
1708
+
1709
+ server.addSchema(someSchema)
1710
+
1711
+ server.register((instance, opts, done) => {
1712
+ instance.addSchema(anotherSchema)
1713
+
1714
+ instance.post(
1715
+ '/',
1716
+ {
1717
+ schema: {
1718
+ query: {
1719
+ msg: {
1720
+ $ref: 'some#'
1721
+ }
1722
+ },
1723
+ headers: {
1724
+ 'x-another': {
1725
+ $ref: 'another#'
1726
+ }
1727
+ }
1728
+ }
1729
+ },
1730
+ (req, reply) => {
1731
+ reply.send({ noop: 'noop' })
1732
+ }
1733
+ )
1734
+
1735
+ done()
1736
+ })
1737
+
1738
+ try {
1739
+ const res = await server.inject({
1740
+ method: 'POST',
1741
+ url: '/',
1742
+ query: {
1743
+ msg: ['string']
1744
+ }
1745
+ })
1746
+
1747
+ t.equal(res.json().message, 'querystring.msg should be array')
1748
+ t.equal(res.statusCode, 400, 'Should not coearce the string into array')
1749
+ } catch (err) {
1750
+ t.error(err)
1751
+ }
1752
+ })
@@ -16,6 +16,15 @@ const Readable = require('stream').Readable
16
16
  const split = require('split2')
17
17
  const { kDisableRequestLogging, kReplySent } = require('../lib/symbols.js')
18
18
 
19
+ function getUrl (app) {
20
+ const { address, port } = app.server.address()
21
+ if (address === '::1') {
22
+ return `http://[${address}]:${port}`
23
+ } else {
24
+ return `http://${address}:${port}`
25
+ }
26
+ }
27
+
19
28
  test('should respond with a stream', t => {
20
29
  t.plan(8)
21
30
  const fastify = Fastify()
@@ -573,7 +582,7 @@ test('return a 404 if the stream emits a 404 error', t => {
573
582
  })
574
583
  })
575
584
 
576
- test('should support send module 200 and 404', t => {
585
+ test('should support send module 200 and 404', { only: true }, t => {
577
586
  t.plan(8)
578
587
  const fastify = Fastify()
579
588
 
@@ -591,7 +600,9 @@ test('should support send module 200 and 404', t => {
591
600
  t.error(err)
592
601
  fastify.server.unref()
593
602
 
594
- sget(`http://localhost:${fastify.server.address().port}`, function (err, response, data) {
603
+ const url = getUrl(fastify)
604
+
605
+ sget(url, function (err, response, data) {
595
606
  t.error(err)
596
607
  t.equal(response.headers['content-type'], 'application/octet-stream')
597
608
  t.equal(response.statusCode, 200)
@@ -602,7 +613,7 @@ test('should support send module 200 and 404', t => {
602
613
  })
603
614
  })
604
615
 
605
- sget(`http://localhost:${fastify.server.address().port}/error`, function (err, response) {
616
+ sget(url + '/error', function (err, response) {
606
617
  t.error(err)
607
618
  t.equal(response.statusCode, 404)
608
619
  })
@@ -1,9 +1,10 @@
1
1
  'use strict'
2
2
 
3
3
  const t = require('tap')
4
- const test = t.test
4
+ const { test, before } = t
5
5
  const sget = require('simple-get').concat
6
6
  const fastify = require('..')
7
+ const dns = require('dns').promises
7
8
 
8
9
  const sgetForwardedRequest = (app, forHeader, path, protoHeader) => {
9
10
  const headers = {
@@ -38,6 +39,13 @@ const testRequestValues = (t, req, options) => {
38
39
  }
39
40
  }
40
41
 
42
+ let localhost
43
+
44
+ before(async function () {
45
+ const lookup = await dns.lookup('localhost')
46
+ localhost = lookup.address
47
+ })
48
+
41
49
  test('trust proxy, not add properties to node req', (t) => {
42
50
  t.plan(8)
43
51
  const app = fastify({
@@ -49,7 +57,7 @@ test('trust proxy, not add properties to node req', (t) => {
49
57
  })
50
58
 
51
59
  app.get('/trustproxychain', function (req, reply) {
52
- testRequestValues(t, req, { ip: '2.2.2.2', ips: ['127.0.0.1', '1.1.1.1', '2.2.2.2'] })
60
+ testRequestValues(t, req, { ip: '2.2.2.2', ips: [localhost, '1.1.1.1', '2.2.2.2'] })
53
61
  reply.code(200).send({ ip: req.ip, hostname: req.hostname })
54
62
  })
55
63
 
@@ -66,7 +74,7 @@ test('trust proxy, not add properties to node req', (t) => {
66
74
  test('trust proxy chain', (t) => {
67
75
  t.plan(3)
68
76
  const app = fastify({
69
- trustProxy: ['127.0.0.1', '192.168.1.1']
77
+ trustProxy: [localhost, '192.168.1.1']
70
78
  })
71
79
 
72
80
  app.get('/trustproxychain', function (req, reply) {
@@ -86,7 +94,7 @@ test('trust proxy chain', (t) => {
86
94
  test('trust proxy function', (t) => {
87
95
  t.plan(3)
88
96
  const app = fastify({
89
- trustProxy: (address) => address === '127.0.0.1'
97
+ trustProxy: (address) => address === localhost
90
98
  })
91
99
  app.get('/trustproxyfunc', function (req, reply) {
92
100
  testRequestValues(t, req, { ip: '1.1.1.1' })
@@ -108,7 +116,7 @@ test('trust proxy number', (t) => {
108
116
  trustProxy: 1
109
117
  })
110
118
  app.get('/trustproxynumber', function (req, reply) {
111
- testRequestValues(t, req, { ip: '1.1.1.1', ips: ['127.0.0.1', '1.1.1.1'] })
119
+ testRequestValues(t, req, { ip: '1.1.1.1', ips: [localhost, '1.1.1.1'] })
112
120
  reply.code(200).send({ ip: req.ip, hostname: req.hostname })
113
121
  })
114
122
 
@@ -124,10 +132,10 @@ test('trust proxy number', (t) => {
124
132
  test('trust proxy IP addresses', (t) => {
125
133
  t.plan(4)
126
134
  const app = fastify({
127
- trustProxy: '127.0.0.1, 2.2.2.2'
135
+ trustProxy: `${localhost}, 2.2.2.2`
128
136
  })
129
137
  app.get('/trustproxyipaddrs', function (req, reply) {
130
- testRequestValues(t, req, { ip: '1.1.1.1', ips: ['127.0.0.1', '1.1.1.1'] })
138
+ testRequestValues(t, req, { ip: '1.1.1.1', ips: [localhost, '1.1.1.1'] })
131
139
  reply.code(200).send({ ip: req.ip, hostname: req.hostname })
132
140
  })
133
141
 
@@ -3,7 +3,8 @@ import fastify, {
3
3
  FastifyError,
4
4
  FastifyInstance,
5
5
  RawReplyDefaultExpression,
6
- RawRequestDefaultExpression
6
+ RawRequestDefaultExpression,
7
+ RawServerDefault
7
8
  } from '../../fastify'
8
9
  import { expectAssignable, expectError, expectType } from 'tsd'
9
10
  import { FastifyRequest } from '../../types/request'
@@ -51,6 +52,50 @@ server.setErrorHandler(nodeJSErrorHandler)
51
52
  function asyncNodeJSErrorHandler (error: NodeJS.ErrnoException) {}
52
53
  server.setErrorHandler(asyncNodeJSErrorHandler)
53
54
 
55
+ class CustomError extends Error {
56
+ private __brand: any;
57
+ }
58
+ interface ReplyPayload {
59
+ Reply: {
60
+ test: boolean;
61
+ };
62
+ }
63
+ // typed sync error handler
64
+ server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
65
+ expectType<CustomError>(error)
66
+ expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.send)
67
+ })
68
+ // typed async error handler send
69
+ server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
70
+ expectType<CustomError>(error)
71
+ expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.send)
72
+ })
73
+ // typed async error handler return
74
+ server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
75
+ expectType<CustomError>(error)
76
+ return { test: true }
77
+ })
78
+ // typed sync error handler send error
79
+ expectError(server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
80
+ expectType<CustomError>(error)
81
+ reply.send({ test: 'foo' })
82
+ }))
83
+ // typed sync error handler return error
84
+ expectError(server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
85
+ expectType<CustomError>(error)
86
+ return { test: 'foo' }
87
+ }))
88
+ // typed async error handler send error
89
+ expectError(server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
90
+ expectType<CustomError>(error)
91
+ reply.send({ test: 'foo' })
92
+ }))
93
+ // typed async error handler return error
94
+ expectError(server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
95
+ expectType<CustomError>(error)
96
+ return { test: 'foo' }
97
+ }))
98
+
54
99
  function notFoundHandler (request: FastifyRequest, reply: FastifyReply) {}
55
100
  function notFoundpreHandlerHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
56
101
  async function notFoundpreHandlerAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
@@ -90,6 +135,12 @@ expectAssignable<void>(server.listen('3000', '', (err, address) => {}))
90
135
  expectAssignable<void>(server.listen(3000, (err, address) => {}))
91
136
  expectAssignable<void>(server.listen('3000', (err, address) => {}))
92
137
 
138
+ // test listen method callback types
139
+ expectAssignable<void>(server.listen('3000', (err, address) => {
140
+ expectAssignable<Error|null>(err)
141
+ expectAssignable<string>(address)
142
+ }))
143
+
93
144
  // test listen method promise
94
145
  expectAssignable<PromiseLike<string>>(server.listen(3000))
95
146
  expectAssignable<PromiseLike<string>>(server.listen('3000'))
@@ -1,5 +1,5 @@
1
1
  import { expectType } from 'tsd'
2
- import fastify, { RouteHandler, RawRequestDefaultExpression, RequestBodyDefault, RequestGenericInterface } from '../../fastify'
2
+ import fastify, { RouteHandler, RawRequestDefaultExpression, RequestBodyDefault, RequestGenericInterface, FastifyContext, ContextConfigDefault, FastifyContextConfig } from '../../fastify'
3
3
  import { RequestParamsDefault, RequestHeadersDefault, RequestQuerystringDefault } from '../../types/utils'
4
4
  import { FastifyLoggerInstance } from '../../types/logger'
5
5
  import { FastifyRequest } from '../../types/request'
@@ -50,6 +50,8 @@ const getHandler: RouteHandler = function (request, _reply) {
50
50
  expectType<RawRequestDefaultExpression>(request.raw)
51
51
  expectType<RequestBodyDefault>(request.body)
52
52
  expectType<RequestParamsDefault>(request.params)
53
+ expectType<FastifyContext<ContextConfigDefault>>(request.context)
54
+ expectType<FastifyContextConfig>(request.context.config)
53
55
 
54
56
  expectType<RequestHeadersDefault & RawRequestDefaultExpression['headers']>(request.headers)
55
57
  request.headers = {}
@@ -72,6 +74,8 @@ const postHandler: Handler = function (request) {
72
74
  expectType<number>(request.params.id)
73
75
  expectType<string>(request.headers['x-foobar'])
74
76
  expectType<FastifyInstance>(request.server)
77
+ expectType<FastifyContext<ContextConfigDefault>>(request.context)
78
+ expectType<FastifyContextConfig>(request.context.config)
75
79
  }
76
80
 
77
81
  function putHandler (request: CustomRequest, reply: FastifyReply) {
@@ -84,6 +88,8 @@ function putHandler (request: CustomRequest, reply: FastifyReply) {
84
88
  expectType<number>(request.params.id)
85
89
  expectType<string>(request.headers['x-foobar'])
86
90
  expectType<FastifyInstance>(request.server)
91
+ expectType<FastifyContext<ContextConfigDefault>>(request.context)
92
+ expectType<FastifyContextConfig>(request.context.config)
87
93
  }
88
94
 
89
95
  const server = fastify()