fastify 5.11.3 → 5.12.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 (47) hide show
  1. package/.pi/self-learning-memory/README.md +8 -0
  2. package/.pi/self-learning-memory/core/CORE.md +33 -0
  3. package/.pi/self-learning-memory/core/index.json +735 -0
  4. package/.pi/self-learning-memory/daily/2026-07-06.md +22 -0
  5. package/.pi/self-learning-memory/daily/2026-07-29.md +50 -0
  6. package/.pi/self-learning-memory/daily/2026-08-04.md +41 -0
  7. package/.pi/self-learning-memory/daily/2026-08-18.md +40 -0
  8. package/.pi/self-learning-memory/long-term-memory.md +89 -0
  9. package/AGENTS.md +290 -0
  10. package/SPONSORS.md +1 -0
  11. package/docs/Guides/Serverless.md +34 -2
  12. package/docs/Reference/Reply.md +14 -0
  13. package/docs/Reference/Server.md +8 -3
  14. package/fastify.d.ts +1 -1
  15. package/fastify.js +2 -2
  16. package/lib/content-type.js +4 -1
  17. package/lib/reply.js +11 -1
  18. package/lib/request.js +3 -2
  19. package/lib/route.js +2 -1
  20. package/lib/validation.js +10 -1
  21. package/package.json +2 -3
  22. package/test/close.test.js +34 -0
  23. package/test/content-parser.test.js +16 -18
  24. package/test/content-type.test.js +4 -0
  25. package/test/fix-root-primitive-coercion.test.js +35 -0
  26. package/test/helper.js +73 -1
  27. package/test/hooks-async.test.js +1 -2
  28. package/test/hooks.test.js +1 -2
  29. package/test/internals/reply.test.js +76 -1
  30. package/test/listen.1.test.js +17 -52
  31. package/test/listen.5.test.js +6 -9
  32. package/test/logger/instantiation.test.js +1 -1
  33. package/test/logger/logging.test.js +1 -1
  34. package/test/logger/request.test.js +1 -1
  35. package/test/logger/response.test.js +1 -1
  36. package/test/plugin.4.test.js +5 -4
  37. package/test/reply-media-type.test.js +131 -0
  38. package/test/route-prefix.test.js +33 -1
  39. package/test/route.6.test.js +4 -11
  40. package/test/schema-feature.test.js +36 -65
  41. package/test/schema-serialization.test.js +1 -1
  42. package/test/schema-special-usage.test.js +1 -1
  43. package/test/schema-validation.test.js +1 -1
  44. package/test/stream.2.test.js +1 -1
  45. package/test/trust-proxy.test.js +27 -21
  46. package/test/types/fastify.tst.ts +2 -0
  47. package/test/toolkit.js +0 -63
package/fastify.d.ts CHANGED
@@ -149,7 +149,7 @@ declare namespace fastify {
149
149
  requestIdLogLabel?: string;
150
150
  useSemicolonDelimiter?: boolean,
151
151
  genReqId?: (req: RawRequestDefaultExpression<RawServer>) => string,
152
- trustProxy?: boolean | string | string[] | number | TrustProxyFunction,
152
+ trustProxy?: boolean | string | string[] | TrustProxyFunction,
153
153
  querystringParser?: (str: string) => { [key: string]: unknown },
154
154
  constraints?: {
155
155
  [name: string]: ConstraintStrategy<FindMyWayVersion<RawServer>, unknown>,
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '5.11.3'
3
+ const VERSION = '5.12.1'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('node:http')
@@ -601,7 +601,7 @@ function fastify (serverOptions) {
601
601
 
602
602
  if (name === 'onClose') {
603
603
  this.onClose(fn.bind(this))
604
- } else if (name === 'onReady' || name === 'onListen' || name === 'onRoute') {
604
+ } else if (name === 'onReady' || name === 'onListen' || name === 'onRoute' || name === 'preClose') {
605
605
  this[kHooks].add(name, fn)
606
606
  } else {
607
607
  this.after((err, done) => {
@@ -183,7 +183,10 @@ class ContentType {
183
183
 
184
184
  get isValid () { return this.#valid }
185
185
 
186
- get mediaType () { return `${this.#type}/${this.#subtype}` }
186
+ get mediaType () {
187
+ if (this.#valid === false) return undefined
188
+ return `${this.#type}/${this.#subtype}`
189
+ }
187
190
 
188
191
  get type () { return this.#type }
189
192
 
package/lib/reply.js CHANGED
@@ -93,6 +93,12 @@ Object.defineProperties(Reply.prototype, {
93
93
  return (this[kReplyEndTime] || now()) - this[kReplyStartTime]
94
94
  }
95
95
  },
96
+ mediaType: {
97
+ get () {
98
+ const contentTypeHeader = this[kReplyHeaders]['content-type']
99
+ return ContentType.from(contentTypeHeader).mediaType
100
+ }
101
+ },
96
102
  server: {
97
103
  get () {
98
104
  return this.request[kRouteContext].server
@@ -254,9 +260,13 @@ Reply.prototype.hasHeader = function (key) {
254
260
  }
255
261
 
256
262
  Reply.prototype.removeHeader = function (key) {
263
+ key = key.toLowerCase()
257
264
  // Node.js does not like headers with keys set to undefined,
258
265
  // so we have to delete the key.
259
- delete this[kReplyHeaders][key.toLowerCase()]
266
+ delete this[kReplyHeaders][key]
267
+ if (!this.raw.headersSent) {
268
+ this.raw.removeHeader(key)
269
+ }
260
270
  return this
261
271
  }
262
272
 
package/lib/request.js CHANGED
@@ -49,8 +49,9 @@ function getTrustProxyFn (tp) {
49
49
  return function () { return true }
50
50
  }
51
51
  if (typeof tp === 'number') {
52
- // Support trusting hop count
53
- return function (a, i) { return i < tp }
52
+ // Hop-count-only trust cannot validate the immediate peer. Fail closed so
53
+ // direct clients cannot spoof X-Forwarded-* values by supplying enough hops.
54
+ return function () { return false }
54
55
  }
55
56
  if (typeof tp === 'string') {
56
57
  // Support comma-separated tps
package/lib/route.js CHANGED
@@ -290,6 +290,7 @@ function buildRouting (options) {
290
290
  opts.attachValidation = false
291
291
  }
292
292
 
293
+ const routeConfigUrl = prefixing ? prefix : url
293
294
  if (prefixing === false) {
294
295
  // run 'onRoute' hooks
295
296
  for (const hook of this[kHooks].onRoute) {
@@ -328,7 +329,7 @@ function buildRouting (options) {
328
329
  const constraints = opts.constraints || {}
329
330
  const config = {
330
331
  ...opts.config,
331
- url,
332
+ url: routeConfigUrl,
332
333
  method: opts.method
333
334
  }
334
335
 
package/lib/validation.js CHANGED
@@ -120,7 +120,16 @@ function validateParam (validatorFunction, request, paramName) {
120
120
  let ret
121
121
 
122
122
  try {
123
- ret = validatorFunction?.(isUndefined ? null : request[paramName])
123
+ const data = isUndefined ? null : request[paramName]
124
+ // Ajv can only mutate a root value when its parent is provided.
125
+ if (validatorFunction?.schemaEnv) {
126
+ ret = validatorFunction(data, {
127
+ parentData: request,
128
+ parentDataProperty: paramName
129
+ })
130
+ } else {
131
+ ret = validatorFunction?.(data)
132
+ }
124
133
  } catch (err) {
125
134
  // If validator throws synchronously, ensure it propagates as an internal error
126
135
  err.statusCode = 500
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "5.11.3",
3
+ "version": "5.12.1",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -167,7 +167,6 @@
167
167
  ],
168
168
  "devDependencies": {
169
169
  "@jsumners/line-reporter": "^1.0.1",
170
- "@sinonjs/fake-timers": "^11.2.2",
171
170
  "@stylistic/eslint-plugin": "^5.1.0",
172
171
  "@stylistic/eslint-plugin-js": "^4.1.0",
173
172
  "@types/node": "^26.0.1",
@@ -214,7 +213,7 @@
214
213
  "find-my-way": "^9.6.0",
215
214
  "light-my-request": "^6.0.0",
216
215
  "pino": "^9.14.0 || ^10.1.0",
217
- "process-warning": "^5.0.0",
216
+ "process-warning": "^5.1.0",
218
217
  "rfdc": "^1.3.1",
219
218
  "secure-json-parse": "^4.0.0",
220
219
  "semver": "^7.6.0",
@@ -665,6 +665,40 @@ test('preClose async', async t => {
665
665
  await fastify.close()
666
666
  })
667
667
 
668
+ test('preClose runs exactly once with a child plugin', async t => {
669
+ t.plan(1)
670
+ const fastify = Fastify()
671
+ let count = 0
672
+
673
+ fastify.register(async (child) => {
674
+ child.get('/x', async () => 'ok')
675
+ })
676
+ fastify.addHook('preClose', async () => { count++ })
677
+
678
+ await fastify.ready()
679
+ await fastify.close()
680
+
681
+ t.assert.strictEqual(count, 1)
682
+ })
683
+
684
+ test('preClose runs exactly once with nested child plugins', async t => {
685
+ t.plan(1)
686
+ const fastify = Fastify()
687
+ let count = 0
688
+
689
+ fastify.register(async (child) => {
690
+ child.register(async (grandchild) => {
691
+ grandchild.get('/y', async () => 'ok')
692
+ })
693
+ })
694
+ fastify.addHook('preClose', async () => { count++ })
695
+
696
+ await fastify.ready()
697
+ await fastify.close()
698
+
699
+ t.assert.strictEqual(count, 1)
700
+ })
701
+
668
702
  test('preClose execution order', (t, done) => {
669
703
  t.plan(4)
670
704
  const fastify = Fastify()
@@ -1,9 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('node:test')
4
+ const { spyWarning } = require('process-warning')
4
5
  const Fastify = require('..')
5
6
  const keys = require('../lib/symbols')
6
7
  const { FST_ERR_CTP_ALREADY_PRESENT, FST_ERR_CTP_INVALID_TYPE, FST_ERR_CTP_INVALID_MEDIA_TYPE } = require('../lib/errors')
8
+ const { FSTSEC001 } = require('../lib/warnings')
7
9
 
8
10
  const first = function (req, payload, done) {}
9
11
  const second = function (req, payload, done) {}
@@ -488,41 +490,37 @@ test('Safeguard against content-type spoofing - string', async t => {
488
490
  })
489
491
 
490
492
  test('Warning against improper content-type - regexp', async t => {
491
- await t.test('improper regex - text plain', (t, done) => {
493
+ await t.test('improper regex - text plain', async (t) => {
492
494
  t.plan(2)
493
- const fastify = Fastify()
495
+ const spyData = spyWarning(FSTSEC001)
496
+ t.after(spyData.restore)
494
497
 
495
- process.on('warning', onWarning)
496
- function onWarning (warning) {
497
- t.assert.strictEqual(warning.name, 'FastifySecurity')
498
- t.assert.strictEqual(warning.code, 'FSTSEC001')
499
- done()
500
- }
501
- t.after(() => process.removeListener('warning', onWarning))
498
+ const fastify = Fastify()
502
499
 
503
500
  fastify.removeAllContentTypeParsers()
504
501
  fastify.addContentTypeParser(/text\/plain/, function (request, body, done) {
505
502
  done(null, body)
506
503
  })
504
+
505
+ await fastify.ready()
506
+ t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['text\\/plain'], result: true }])
507
+ t.assert.strictEqual(spyData.callCount(), 1)
507
508
  })
508
509
 
509
- await t.test('improper regex - application json', (t, done) => {
510
+ await t.test('improper regex - application json', async (t) => {
510
511
  t.plan(2)
512
+ const spyData = spyWarning(FSTSEC001)
513
+ t.after(spyData.restore)
511
514
  const fastify = Fastify()
512
515
 
513
- process.on('warning', onWarning)
514
- function onWarning (warning) {
515
- t.assert.strictEqual(warning.name, 'FastifySecurity')
516
- t.assert.strictEqual(warning.code, 'FSTSEC001')
517
- done()
518
- }
519
- t.after(() => process.removeListener('warning', onWarning))
520
-
521
516
  fastify.removeAllContentTypeParsers()
522
517
 
523
518
  fastify.addContentTypeParser(/application\/json/, function (request, body, done) {
524
519
  done(null, body)
525
520
  })
521
+
522
+ t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['application\\/json'], result: true }])
523
+ t.assert.deepEqual(spyData.callCount(), 1)
526
524
  })
527
525
  })
528
526
 
@@ -46,18 +46,22 @@ describe('ContentType class', () => {
46
46
  test('returns empty instance for empty value', (t) => {
47
47
  let found = new ContentType('')
48
48
  t.assert.equal(found.isEmpty, true)
49
+ t.assert.equal(found.mediaType, undefined)
49
50
 
50
51
  found = new ContentType('undefined')
51
52
  t.assert.equal(found.isEmpty, true)
53
+ t.assert.equal(found.mediaType, undefined)
52
54
 
53
55
  found = new ContentType()
54
56
  t.assert.equal(found.isEmpty, true)
57
+ t.assert.equal(found.mediaType, undefined)
55
58
  })
56
59
 
57
60
  test('indicates media type is not correct format', (t) => {
58
61
  let found = new ContentType('foo')
59
62
  t.assert.equal(found.isEmpty, true)
60
63
  t.assert.equal(found.isValid, false)
64
+ t.assert.equal(found.mediaType, undefined)
61
65
 
62
66
  found = new ContentType('foo /bar')
63
67
  t.assert.equal(found.isEmpty, true)
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const Fastify = require('..')
5
+
6
+ test('root primitive values coerced by Ajv are assigned to the request', async (t) => {
7
+ const fastify = Fastify()
8
+
9
+ fastify.post('/', {
10
+ schema: {
11
+ body: {
12
+ type: 'integer',
13
+ minimum: 1,
14
+ maximum: 10
15
+ }
16
+ }
17
+ }, (request, reply) => {
18
+ reply.send({ body: request.body, type: typeof request.body })
19
+ })
20
+
21
+ const response = await fastify.inject({
22
+ method: 'POST',
23
+ url: '/',
24
+ payload: '"10"',
25
+ headers: { 'content-type': 'application/json' }
26
+ })
27
+
28
+ t.assert.strictEqual(response.statusCode, 200)
29
+ t.assert.deepStrictEqual(JSON.parse(response.payload), {
30
+ body: 10,
31
+ type: 'number'
32
+ })
33
+
34
+ await fastify.close()
35
+ })
package/test/helper.js CHANGED
@@ -4,11 +4,42 @@ const dns = require('node:dns').promises
4
4
  const stream = require('node:stream')
5
5
  const { promisify } = require('node:util')
6
6
  const symbols = require('../lib/symbols')
7
- const { waitForCb } = require('./toolkit')
8
7
  const assert = require('node:assert')
9
8
 
10
9
  module.exports.sleep = promisify(setTimeout)
11
10
 
11
+ function waitForCb (options) {
12
+ let count = null
13
+ let done = false
14
+ let iResolve
15
+ let iReject
16
+
17
+ function stepIn () {
18
+ if (done) {
19
+ iReject(new Error('Unexpected done call'))
20
+ return
21
+ }
22
+
23
+ if (--count) {
24
+ return
25
+ }
26
+
27
+ done = true
28
+ iResolve()
29
+ }
30
+
31
+ const patience = new Promise((resolve, reject) => {
32
+ iResolve = resolve
33
+ iReject = reject
34
+ })
35
+
36
+ count = options.steps || 1
37
+ done = false
38
+
39
+ return { stepIn, patience }
40
+ }
41
+ module.exports.waitForCb = waitForCb
42
+
12
43
  /**
13
44
  * @param method HTTP request method
14
45
  * @param t node:test instance
@@ -494,3 +525,44 @@ module.exports.getServerUrl = function (app) {
494
525
  ? `http://[${address}]:${port}`
495
526
  : `http://${address}:${port}`
496
527
  }
528
+
529
+ module.exports.partialDeepStrictEqual = function partialDeepStrictEqual (actual, expected) {
530
+ if (typeof expected !== 'object' || expected === null) {
531
+ return actual === expected
532
+ }
533
+
534
+ if (typeof actual !== 'object' || actual === null) {
535
+ return false
536
+ }
537
+
538
+ if (Array.isArray(expected)) {
539
+ if (!Array.isArray(actual)) return false
540
+ if (expected.length > actual.length) return false
541
+
542
+ for (let i = 0; i < expected.length; i++) {
543
+ if (!partialDeepStrictEqual(actual[i], expected[i])) {
544
+ return false
545
+ }
546
+ }
547
+ return true
548
+ }
549
+
550
+ for (const key of Object.keys(expected)) {
551
+ if (!(key in actual)) return false
552
+ if (!partialDeepStrictEqual(actual[key], expected[key])) {
553
+ return false
554
+ }
555
+ }
556
+
557
+ return true
558
+ }
559
+
560
+ module.exports.assertNoWarning = function (t) {
561
+ function doNotWarn () {
562
+ t.assert.fail('no warning')
563
+ }
564
+ process.on('warning', doNotWarn)
565
+ t.after(() => {
566
+ process.off('warning', doNotWarn)
567
+ })
568
+ }
@@ -4,8 +4,7 @@ const { Readable } = require('node:stream')
4
4
  const { test, describe } = require('node:test')
5
5
  const Fastify = require('../fastify')
6
6
  const fs = require('node:fs')
7
- const { sleep } = require('./helper')
8
- const { waitForCb } = require('./toolkit')
7
+ const { sleep, waitForCb } = require('./helper')
9
8
 
10
9
  process.removeAllListeners('warning')
11
10
 
@@ -10,8 +10,7 @@ const symbols = require('../lib/symbols.js')
10
10
  const payload = { hello: 'world' }
11
11
  const proxyquire = require('proxyquire')
12
12
  const { connect } = require('node:net')
13
- const { sleep } = require('./helper')
14
- const { waitForCb } = require('./toolkit.js')
13
+ const { sleep, waitForCb } = require('./helper')
15
14
  const { fetch } = require('undici')
16
15
 
17
16
  process.removeAllListeners('warning')
@@ -34,7 +34,7 @@ const doGet = async function (url) {
34
34
  }
35
35
 
36
36
  test('Once called, Reply should return an object with methods', t => {
37
- t.plan(15)
37
+ t.plan(16)
38
38
  const response = { res: 'res' }
39
39
  const context = {
40
40
  config: { onSend: [] },
@@ -49,6 +49,7 @@ test('Once called, Reply should return an object with methods', t => {
49
49
  t.assert.strictEqual(typeof reply[kReplyErrorHandlerCalled], 'boolean')
50
50
  t.assert.strictEqual(typeof reply.send, 'function')
51
51
  t.assert.strictEqual(typeof reply.code, 'function')
52
+ t.assert.strictEqual(typeof reply.mediaType, 'undefined')
52
53
  t.assert.strictEqual(typeof reply.status, 'function')
53
54
  t.assert.strictEqual(typeof reply.header, 'function')
54
55
  t.assert.strictEqual(typeof reply.serialize, 'function')
@@ -1114,6 +1115,80 @@ test('reply.removeHeader can remove the value', async t => {
1114
1115
  await fetch(`${fastifyServer}/headers`)
1115
1116
  })
1116
1117
 
1118
+ test('reply.removeHeader removes raw headers', async t => {
1119
+ t.plan(9)
1120
+
1121
+ const fastify = require('../../')()
1122
+
1123
+ t.after(() => fastify.close())
1124
+
1125
+ fastify.get('/headers', function (req, reply) {
1126
+ reply.raw.setHeader('X-Foo', 'raw')
1127
+ t.assert.strictEqual(reply.getHeader('x-foo'), 'raw')
1128
+ t.assert.strictEqual(reply.getHeaders()['x-foo'], 'raw')
1129
+ t.assert.strictEqual(reply.hasHeader('x-foo'), true)
1130
+
1131
+ t.assert.strictEqual(reply.removeHeader('x-FoO'), reply)
1132
+ t.assert.strictEqual(reply.getHeader('x-foo'), undefined)
1133
+ t.assert.strictEqual(Object.hasOwn(reply.getHeaders(), 'x-foo'), false)
1134
+ t.assert.strictEqual(reply.hasHeader('x-foo'), false)
1135
+ t.assert.strictEqual(reply.removeHeader('X-FOO'), reply)
1136
+
1137
+ reply.send()
1138
+ })
1139
+
1140
+ const fastifyServer = await fastify.listen({ port: 0 })
1141
+ const response = await fetch(`${fastifyServer}/headers`)
1142
+ t.assert.strictEqual(response.headers.get('x-foo'), null)
1143
+ })
1144
+
1145
+ test('reply.removeHeader removes layered headers', async t => {
1146
+ t.plan(7)
1147
+
1148
+ const fastify = require('../../')()
1149
+
1150
+ t.after(() => fastify.close())
1151
+
1152
+ fastify.get('/headers', function (req, reply) {
1153
+ reply.raw.setHeader('x-foo', 'raw')
1154
+ reply.header('x-foo', 'fastify')
1155
+ t.assert.strictEqual(reply.getHeader('x-foo'), 'fastify')
1156
+ t.assert.strictEqual(reply.getHeaders()['x-foo'], 'fastify')
1157
+
1158
+ t.assert.strictEqual(reply.removeHeader('x-foo'), reply)
1159
+ t.assert.strictEqual(reply.getHeader('x-foo'), undefined)
1160
+ t.assert.strictEqual(Object.hasOwn(reply.getHeaders(), 'x-foo'), false)
1161
+ t.assert.strictEqual(reply.hasHeader('x-foo'), false)
1162
+
1163
+ reply.send()
1164
+ })
1165
+
1166
+ const fastifyServer = await fastify.listen({ port: 0 })
1167
+ const response = await fetch(`${fastifyServer}/headers`)
1168
+ t.assert.strictEqual(response.headers.get('x-foo'), null)
1169
+ })
1170
+
1171
+ test('reply.removeHeader does not throw after headers are sent', async t => {
1172
+ t.plan(3)
1173
+
1174
+ const fastify = require('../../')()
1175
+
1176
+ t.after(() => fastify.close())
1177
+
1178
+ fastify.get('/headers', function (req, reply) {
1179
+ reply.hijack()
1180
+ reply.raw.setHeader('x-foo', 'raw')
1181
+ reply.raw.flushHeaders()
1182
+ t.assert.strictEqual(reply.raw.headersSent, true)
1183
+ t.assert.doesNotThrow(() => reply.removeHeader('x-foo'))
1184
+ reply.raw.end()
1185
+ })
1186
+
1187
+ const fastifyServer = await fastify.listen({ port: 0 })
1188
+ const response = await fetch(`${fastifyServer}/headers`)
1189
+ t.assert.strictEqual(response.headers.get('x-foo'), 'raw')
1190
+ })
1191
+
1117
1192
  test('reply.header can reset the value', async t => {
1118
1193
  t.plan(1)
1119
1194
 
@@ -4,6 +4,7 @@ const { networkInterfaces } = require('node:os')
4
4
  const { test, before } = require('node:test')
5
5
  const Fastify = require('..')
6
6
  const helper = require('./helper')
7
+ const { assertNoWarning } = require('./helper')
7
8
 
8
9
  let localhost
9
10
  let localhostForURL
@@ -13,33 +14,22 @@ before(async function () {
13
14
  })
14
15
 
15
16
  test('listen works without arguments', async t => {
16
- const doNotWarn = () => {
17
- t.assert.fail('should not be deprecated')
18
- }
19
- process.on('warning', doNotWarn)
17
+ assertNoWarning(t)
20
18
 
21
19
  const fastify = Fastify()
22
- t.after(() => {
23
- fastify.close()
24
- process.removeListener('warning', doNotWarn)
25
- })
20
+
26
21
  await fastify.listen()
27
22
  const address = fastify.server.address()
28
23
  t.assert.strictEqual(address.address, localhost)
29
24
  t.assert.ok(address.port > 0)
25
+ await fastify.close()
30
26
  })
31
27
 
32
28
  test('Async/await listen with arguments', async t => {
33
- const doNotWarn = () => {
34
- t.assert.fail('should not be deprecated')
35
- }
36
- process.on('warning', doNotWarn)
29
+ assertNoWarning(t)
37
30
 
38
31
  const fastify = Fastify()
39
- t.after(() => {
40
- fastify.close()
41
- process.removeListener('warning', doNotWarn)
42
- })
32
+
43
33
  const addr = await fastify.listen({ port: 0, host: '0.0.0.0' })
44
34
  const address = fastify.server.address()
45
35
  const { protocol, hostname, port, pathname } = new URL(addr)
@@ -55,39 +45,27 @@ test('Async/await listen with arguments', async t => {
55
45
  family: 'IPv4',
56
46
  port: address.port
57
47
  })
48
+ await fastify.close()
58
49
  })
59
50
 
60
51
  test('listen accepts a callback', (t, done) => {
61
52
  t.plan(2)
62
- const doNotWarn = () => {
63
- t.assert.fail('should not be deprecated')
64
- }
65
- process.on('warning', doNotWarn)
53
+ assertNoWarning(t)
66
54
 
67
55
  const fastify = Fastify()
68
- t.after(() => {
69
- fastify.close()
70
- process.removeListener('warning', doNotWarn)
71
- })
56
+
72
57
  fastify.listen({ port: 0 }, (err) => {
73
58
  t.assert.ifError(err)
74
59
  t.assert.strictEqual(fastify.server.address().address, localhost)
75
- done()
60
+ fastify.close(done)
76
61
  })
77
62
  })
78
63
 
79
64
  test('listen accepts options and a callback', (t, done) => {
80
65
  t.plan(1)
81
- const doNotWarn = () => {
82
- t.assert.fail('should not be deprecated')
83
- }
84
- process.on('warning', doNotWarn)
66
+ assertNoWarning(t)
85
67
 
86
68
  const fastify = Fastify()
87
- t.after(() => {
88
- fastify.close()
89
- process.removeListener('warning', doNotWarn)
90
- })
91
69
  fastify.listen({
92
70
  port: 0,
93
71
  host: 'localhost',
@@ -98,7 +76,7 @@ test('listen accepts options and a callback', (t, done) => {
98
76
  ipv6Only: false
99
77
  }, (err) => {
100
78
  t.assert.ifError(err)
101
- done()
79
+ fastify.close(done)
102
80
  })
103
81
  })
104
82
 
@@ -118,37 +96,24 @@ test('listen after Promise.resolve()', (t, done) => {
118
96
  })
119
97
 
120
98
  test('listen works with undefined host', async t => {
121
- const doNotWarn = () => {
122
- t.assert.fail('should not be deprecated')
123
- }
124
- process.on('warning', doNotWarn)
99
+ assertNoWarning(t)
125
100
 
126
101
  const fastify = Fastify()
127
- t.after(() => fastify.close())
128
- t.after(() => {
129
- fastify.close()
130
- process.removeListener('warning', doNotWarn)
131
- })
132
102
  await fastify.listen({ host: undefined, port: 0 })
133
103
  const address = fastify.server.address()
134
104
  t.assert.strictEqual(address.address, localhost)
135
105
  t.assert.ok(address.port > 0)
106
+ await fastify.close()
136
107
  })
137
108
 
138
109
  test('listen works with null host', async t => {
139
- const doNotWarn = () => {
140
- t.fail('should not be deprecated')
141
- }
142
- process.on('warning', doNotWarn)
110
+ assertNoWarning(t)
143
111
 
144
112
  const fastify = Fastify()
145
- t.after(() => fastify.close())
146
- t.after(() => {
147
- fastify.close()
148
- process.removeListener('warning', doNotWarn)
149
- })
113
+
150
114
  await fastify.listen({ host: null, port: 0 })
151
115
  const address = fastify.server.address()
152
116
  t.assert.strictEqual(address.address, localhost)
153
117
  t.assert.ok(address.port > 0)
118
+ await fastify.close()
154
119
  })