fastify 5.12.0 → 6.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 (51) hide show
  1. package/README.md +2 -2
  2. package/build/build-validation.js +20 -34
  3. package/docs/Guides/Getting-Started.md +2 -2
  4. package/docs/Reference/Errors.md +5 -3
  5. package/docs/Reference/Hooks.md +0 -4
  6. package/docs/Reference/LTS.md +6 -5
  7. package/docs/Reference/Server.md +8 -88
  8. package/docs/Reference/TypeScript.md +3 -49
  9. package/docs/Reference/Warnings.md +4 -11
  10. package/fastify.d.ts +10 -24
  11. package/fastify.js +17 -34
  12. package/lib/config-validator.js +368 -475
  13. package/lib/errors.js +9 -3
  14. package/lib/log-controller.js +2 -4
  15. package/lib/logger-factory.js +1 -1
  16. package/lib/route.js +4 -9
  17. package/lib/server.js +2 -3
  18. package/lib/warnings.js +2 -46
  19. package/package.json +2 -2
  20. package/test/404s.test.js +0 -49
  21. package/test/allow-unsafe-regex.test.js +12 -4
  22. package/test/case-insensitive.test.js +12 -4
  23. package/test/custom-querystring-parser.test.js +0 -16
  24. package/test/hooks.test.js +6 -1
  25. package/test/http-methods/custom-http-methods.test.js +12 -17
  26. package/test/http-methods/trace.test.js +1 -1
  27. package/test/https/custom-https-server.test.js +1 -1
  28. package/test/internals/errors.test.js +15 -5
  29. package/test/internals/initial-config.test.js +56 -38
  30. package/test/internals/logger.test.js +17 -4
  31. package/test/internals/reply.test.js +1 -1
  32. package/test/internals/request.test.js +8 -24
  33. package/test/logger/logging.test.js +2 -121
  34. package/test/logger/request.test.js +1 -36
  35. package/test/route-prefix.test.js +46 -18
  36. package/test/route.1.test.js +2 -2
  37. package/test/router-options.test.js +25 -523
  38. package/test/set-error-handler.test.js +7 -9
  39. package/test/types/errors.tst.ts +2 -1
  40. package/test/types/fastify.tst.ts +44 -48
  41. package/test/types/instance.tst.ts +4 -5
  42. package/test/types/logger.tst.ts +3 -7
  43. package/test/use-semicolon-delimiter.test.js +0 -60
  44. package/types/context.d.ts +0 -20
  45. package/types/errors.d.ts +2 -1
  46. package/types/instance.d.ts +0 -4
  47. package/types/logger.d.ts +1 -16
  48. package/types/plugin.d.ts +0 -9
  49. package/types/request.d.ts +0 -4
  50. package/lib/promise.js +0 -23
  51. package/test/internals/promise.test.js +0 -63
package/lib/errors.js CHANGED
@@ -416,6 +416,12 @@ const codes = {
416
416
  500,
417
417
  TypeError
418
418
  ),
419
+ FST_ERR_ROUTE_METHOD_ALREADY_SUPPORTED: createError(
420
+ 'FST_ERR_ROUTE_METHOD_ALREADY_SUPPORTED',
421
+ 'Method "%s" is already supported. Use `overrideExisting: true` to override it.',
422
+ 500,
423
+ TypeError
424
+ ),
419
425
  FST_ERR_ROUTE_METHOD_NOT_SUPPORTED: createError(
420
426
  'FST_ERR_ROUTE_METHOD_NOT_SUPPORTED',
421
427
  '%s method is not supported.',
@@ -475,10 +481,10 @@ const codes = {
475
481
  ),
476
482
  FST_ERR_REOPENED_SERVER: createError(
477
483
  'FST_ERR_REOPENED_SERVER',
478
- 'Fastify is already listening'
484
+ 'Fastify is already started'
479
485
  ),
480
- FST_ERR_INSTANCE_ALREADY_LISTENING: createError(
481
- 'FST_ERR_INSTANCE_ALREADY_LISTENING',
486
+ FST_ERR_INSTANCE_ALREADY_STARTED: createError(
487
+ 'FST_ERR_INSTANCE_ALREADY_STARTED',
482
488
  'Fastify instance is already listening. %s'
483
489
  ),
484
490
 
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const { defaultInitOptions } = require('./initial-config-validation')
4
-
5
3
  /**
6
4
  * Internal logger layer that wraps Fastify's log calls with
7
5
  * request-lifecycle awareness (disable-check, level selection).
@@ -20,9 +18,9 @@ class LogController {
20
18
  */
21
19
  constructor (options) {
22
20
  const opts = options || {}
23
- this.disableRequestLogging = opts.disableRequestLogging || defaultInitOptions.disableRequestLogging
21
+ this.disableRequestLogging = opts.disableRequestLogging || false
24
22
  this.isDisableRequestLoggingFunction = typeof this.disableRequestLogging === 'function'
25
- this.requestIdLogLabel = opts.requestIdLogLabel || defaultInitOptions.requestIdLogLabel
23
+ this.requestIdLogLabel = opts.requestIdLogLabel || 'reqId'
26
24
  }
27
25
 
28
26
  /**
@@ -132,7 +132,7 @@ function createLogger (options) {
132
132
  function createLogController (options) {
133
133
  const userController = options.logController
134
134
  if (!userController) {
135
- return new LogController(options)
135
+ return new LogController()
136
136
  }
137
137
 
138
138
  if (userController instanceof LogController) {
package/lib/route.js CHANGED
@@ -6,6 +6,7 @@ const handleRequest = require('./handle-request.js')
6
6
  const { onRequestAbortHookRunner, lifecycleHooks, preParsingHookRunner, onTimeoutHookRunner, onRequestHookRunner } = require('./hooks')
7
7
  const { normalizeSchema } = require('./schemas')
8
8
  const { parseHeadOnSendHandlers } = require('./head-route.js')
9
+ const { defaultInitOptions } = require('./initial-config-validation.js')
9
10
 
10
11
  const {
11
12
  compileSchemasForValidation,
@@ -57,8 +58,6 @@ const {
57
58
  const { buildErrorHandler } = require('./error-handler')
58
59
  const { createChildLogger, defaultChildLoggerFactory } = require('./logger-factory.js')
59
60
  const { getGenReqId } = require('./req-id-gen-factory.js')
60
- const { FSTDEP022 } = require('./warnings')
61
-
62
61
  const routerKeys = [
63
62
  'allowUnsafeRegex',
64
63
  'buildPrettyMeta',
@@ -663,15 +662,11 @@ function buildRouterOptions (options, defaultOptions) {
663
662
  ? Object.create(null)
664
663
  : Object.assign(Object.create(null), options.routerOptions)
665
664
 
666
- const usedDeprecatedOptions = routerKeys.filter(key => Object.hasOwn(options, key))
667
-
668
- if (usedDeprecatedOptions.length > 0) {
669
- FSTDEP022(usedDeprecatedOptions.join(', '))
670
- }
671
-
672
665
  for (const key of routerKeys) {
673
666
  if (!Object.hasOwn(routerOptions, key)) {
674
- routerOptions[key] = options[key] ?? defaultOptions[key]
667
+ // defaultInitOptions are non-function default
668
+ // defaultOptions are function default
669
+ routerOptions[key] = options[key] ?? defaultInitOptions.routerOptions[key] ?? defaultOptions[key]
675
670
  }
676
671
  }
677
672
 
package/lib/server.js CHANGED
@@ -16,7 +16,6 @@ const {
16
16
  FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE
17
17
  } = require('./errors')
18
18
  const noopSet = require('./noop-set')
19
- const PonyPromise = require('./promise')
20
19
 
21
20
  module.exports.createServer = createServer
22
21
 
@@ -106,7 +105,7 @@ function createServer (options, httpHandler) {
106
105
  if (cb === undefined) {
107
106
  const listening = listenPromise.call(this, server, listenOptions)
108
107
  return listening.then(address => {
109
- const { promise, resolve } = PonyPromise.withResolvers()
108
+ const { promise, resolve } = Promise.withResolvers()
110
109
  if (host === 'localhost') {
111
110
  multipleBindings.call(this, server, httpHandler, options, listenOptions, () => {
112
111
  this[kState].listening = true
@@ -277,7 +276,7 @@ function listenPromise (server, listenOptions) {
277
276
  // skip listen when aborted during ready
278
277
  if (this[kState].aborted) return
279
278
 
280
- const { promise, resolve, reject } = PonyPromise.withResolvers()
279
+ const { promise, resolve, reject } = Promise.withResolvers()
281
280
 
282
281
  const errEventHandler = (err) => {
283
282
  cleanup()
package/lib/warnings.js CHANGED
@@ -3,13 +3,9 @@
3
3
  const { createWarning } = require('process-warning')
4
4
 
5
5
  /**
6
- * Deprecation codes:
6
+ * Warning codes:
7
7
  * - FSTWRN001
8
8
  * - FSTSEC001
9
- * - FSTDEP022
10
- * - FSTDEP023
11
- * - FSTDEP024
12
- * - FSTDEP025
13
9
  *
14
10
  * Deprecation Codes FSTDEP001 - FSTDEP021 were used by v4 and MUST NOT be reused.
15
11
  * - FSTDEP022 - FSTDEP025 are used by v5 and MUST NOT be reused.
@@ -30,13 +26,6 @@ const FSTWRN003 = createWarning({
30
26
  unlimited: true
31
27
  })
32
28
 
33
- const FSTWRN004 = createWarning({
34
- name: 'FastifyWarning',
35
- code: 'FSTWRN004',
36
- message: 'It seems that you are overriding an errorHandler in the same scope, which can lead to subtle bugs. To disable this behavior, set \'allowErrorHandlerOverride\' to false. For more information, visit: https://fastify.dev/docs/latest/Reference/Server/#allowerrorhandleroverride',
37
- unlimited: true
38
- })
39
-
40
29
  const FSTSEC001 = createWarning({
41
30
  name: 'FastifySecurity',
42
31
  code: 'FSTSEC001',
@@ -44,41 +33,8 @@ const FSTSEC001 = createWarning({
44
33
  unlimited: true
45
34
  })
46
35
 
47
- const FSTDEP022 = createWarning({
48
- name: 'FastifyWarning',
49
- code: 'FSTDEP022',
50
- message: 'The router options for %s property access is deprecated. Please use "options.routerOptions" instead for accessing router options. The router options will be removed in `fastify@6`.',
51
- unlimited: true
52
- })
53
-
54
- const FSTDEP023 = createWarning({
55
- name: 'FastifyDeprecation',
56
- code: 'FSTDEP023',
57
- message: 'disableRequestLogging option is deprecated. Use the logController option with disableRequestLogging or isLogDisabled override instead. The disableRequestLogging top-level option will be removed in `fastify@6`.',
58
- unlimited: true
59
- })
60
-
61
- const FSTDEP024 = createWarning({
62
- name: 'FastifyDeprecation',
63
- code: 'FSTDEP024',
64
- message: 'requestIdLogLabel option is deprecated. Use the logController option with requestIdLogLabel instead. The requestIdLogLabel top-level option will be removed in `fastify@6`.',
65
- unlimited: true
66
- })
67
-
68
- const FSTDEP025 = createWarning({
69
- name: 'FastifyDeprecation',
70
- code: 'FSTDEP025',
71
- message: 'Calling addHttpMethod for existing method "%s" without { overrideExisting: true } is deprecated. In Fastify v6, this will throw an error.',
72
- unlimited: true
73
- })
74
-
75
36
  module.exports = {
76
37
  FSTWRN001,
77
38
  FSTWRN003,
78
- FSTWRN004,
79
- FSTSEC001,
80
- FSTDEP022,
81
- FSTDEP023,
82
- FSTDEP024,
83
- FSTDEP025
39
+ FSTSEC001
84
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "5.12.0",
3
+ "version": "6.0.0-alpha.1",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -198,7 +198,7 @@
198
198
  "tstyche": "^7.0.0",
199
199
  "typebox": "^1.0.81",
200
200
  "typescript": "~6.0.2",
201
- "undici": "^7.11.0",
201
+ "undici": "^8.0.0",
202
202
  "vary": "^1.1.2",
203
203
  "yup": "^1.4.0"
204
204
  },
package/test/404s.test.js CHANGED
@@ -1984,52 +1984,3 @@ test('hooks are applied to not found handlers /3', async t => {
1984
1984
  const { statusCode } = await fastify.inject('/')
1985
1985
  t.assert.strictEqual(statusCode, 401)
1986
1986
  })
1987
-
1988
- test('should honor disableRequestLogging function for 404', async t => {
1989
- t.plan(3)
1990
-
1991
- const Writable = require('node:stream').Writable
1992
-
1993
- const logStream = new Writable()
1994
- logStream.logs = []
1995
- logStream._write = function (chunk, encoding, callback) {
1996
- this.logs.push(JSON.parse(chunk.toString()))
1997
- callback()
1998
- }
1999
-
2000
- const fastify = Fastify({
2001
- logger: {
2002
- level: 'info',
2003
- stream: logStream
2004
- },
2005
- disableRequestLogging: (req) => {
2006
- // Disable logging for URLs containing 'silent'
2007
- return req.url.includes('silent')
2008
- }
2009
- })
2010
-
2011
- fastify.get('/', function (req, reply) {
2012
- reply.send({ hello: 'world' })
2013
- })
2014
-
2015
- t.after(() => { fastify.close() })
2016
-
2017
- // First request to a non-existent route (no 'silent' in URL) - should log
2018
- const response1 = await fastify.inject({
2019
- method: 'GET',
2020
- url: '/not-found'
2021
- })
2022
- t.assert.strictEqual(response1.statusCode, 404)
2023
-
2024
- // Second request to a non-existent route with 'silent' in URL - should not log
2025
- const response2 = await fastify.inject({
2026
- method: 'GET',
2027
- url: '/silent-route'
2028
- })
2029
- t.assert.strictEqual(response2.statusCode, 404)
2030
-
2031
- // Check logs: first request should have logged, second should not
2032
- // We expect: incoming request, Route not found info, request completed (for first request only)
2033
- const infoLogs = logStream.logs.filter(log => log.msg && log.msg.includes('Route GET:/not-found not found'))
2034
- t.assert.strictEqual(infoLogs.length, 1, 'Should log 404 info only for non-silent route')
2035
- })
@@ -7,7 +7,9 @@ test('allow unsafe regex', async t => {
7
7
  t.plan(2)
8
8
 
9
9
  const fastify = Fastify({
10
- allowUnsafeRegex: false
10
+ routerOptions: {
11
+ allowUnsafeRegex: false
12
+ }
11
13
  })
12
14
  t.after(() => fastify.close())
13
15
 
@@ -26,7 +28,9 @@ test('allow unsafe regex not match', async t => {
26
28
  t.plan(1)
27
29
 
28
30
  const fastify = Fastify({
29
- allowUnsafeRegex: false
31
+ routerOptions: {
32
+ allowUnsafeRegex: false
33
+ }
30
34
  })
31
35
  t.after(() => fastify.close())
32
36
 
@@ -44,7 +48,9 @@ test('allow unsafe regex not safe', (t, done) => {
44
48
  t.plan(1)
45
49
 
46
50
  const fastify = Fastify({
47
- allowUnsafeRegex: false
51
+ routerOptions: {
52
+ allowUnsafeRegex: false
53
+ }
48
54
  })
49
55
  t.after(() => fastify.close())
50
56
 
@@ -74,7 +80,9 @@ test('allow unsafe regex allow unsafe', async t => {
74
80
  t.plan(3)
75
81
 
76
82
  const fastify = Fastify({
77
- allowUnsafeRegex: true
83
+ routerOptions: {
84
+ allowUnsafeRegex: true
85
+ }
78
86
  })
79
87
  t.after(() => fastify.close())
80
88
 
@@ -7,7 +7,9 @@ test('case insensitive', async (t) => {
7
7
  t.plan(3)
8
8
 
9
9
  const fastify = Fastify({
10
- caseSensitive: false
10
+ routerOptions: {
11
+ caseSensitive: false
12
+ }
11
13
  })
12
14
  t.after(() => fastify.close())
13
15
 
@@ -30,7 +32,9 @@ test('case insensitive inject', async t => {
30
32
  t.plan(2)
31
33
 
32
34
  const fastify = Fastify({
33
- caseSensitive: false
35
+ routerOptions: {
36
+ caseSensitive: false
37
+ }
34
38
  })
35
39
  t.after(() => fastify.close())
36
40
 
@@ -55,7 +59,9 @@ test('case insensitive (parametric)', async (t) => {
55
59
  t.plan(4)
56
60
 
57
61
  const fastify = Fastify({
58
- caseSensitive: false
62
+ routerOptions: {
63
+ caseSensitive: false
64
+ }
59
65
  })
60
66
  t.after(() => fastify.close())
61
67
 
@@ -81,7 +87,9 @@ test('case insensitive (wildcard)', async (t) => {
81
87
  t.plan(4)
82
88
 
83
89
  const fastify = Fastify({
84
- caseSensitive: false
90
+ routerOptions: {
91
+ caseSensitive: false
92
+ }
85
93
  })
86
94
  t.after(() => fastify.close())
87
95
 
@@ -94,22 +94,6 @@ test('Querystring without value', async t => {
94
94
  t.assert.strictEqual(injectResponse.statusCode, 200)
95
95
  })
96
96
 
97
- test('Custom querystring parser should be a function', t => {
98
- t.plan(1)
99
-
100
- try {
101
- Fastify({
102
- querystringParser: 10
103
- })
104
- t.assert.fail('Should throw')
105
- } catch (err) {
106
- t.assert.strictEqual(
107
- err.message,
108
- "querystringParser option should be a function, instead got 'number'"
109
- )
110
- }
111
- })
112
-
113
97
  test('Custom querystring parser should be a function', t => {
114
98
  t.plan(1)
115
99
 
@@ -674,7 +674,12 @@ test('onRoute hook should be called once when prefixTrailingSlash', (t, testDone
674
674
  let onRouteCalled = 0
675
675
  let routePatched = 0
676
676
 
677
- const fastify = Fastify({ ignoreTrailingSlash: false, exposeHeadRoutes: false })
677
+ const fastify = Fastify({
678
+ exposeHeadRoutes: false,
679
+ routerOptions: {
680
+ ignoreTrailingSlash: false
681
+ }
682
+ })
678
683
 
679
684
  // a plugin that patches route options, similar to fastify-compress
680
685
  fastify.register(fp(function myPlugin (instance, opts, next) {
@@ -113,36 +113,31 @@ test('addHttpMethod rejects fake http method', t => {
113
113
  t.assert.throws(() => { fastify.addHttpMethod('FOOO') }, /Provided method is invalid!/)
114
114
  })
115
115
 
116
- test('addHttpMethod warns when overriding an existing method', (t, done) => {
116
+ test('addHttpMethod rejects an implicit override of an existing method', t => {
117
117
  const fastify = Fastify()
118
- const onWarning = warning => {
119
- t.assert.strictEqual(warning.name, 'FastifyDeprecation')
120
- t.assert.strictEqual(warning.code, 'FSTDEP025')
121
- done()
122
- }
123
- process.once('warning', onWarning)
124
118
 
125
119
  t.after(() => {
126
120
  fastify.close()
127
- process.removeListener('warning', onWarning)
128
121
  })
129
122
 
130
- fastify.addHttpMethod('GET', { hasBody: true })
123
+ t.assert.throws(
124
+ () => fastify.addHttpMethod('GET', { hasBody: true }),
125
+ {
126
+ code: 'FST_ERR_ROUTE_METHOD_ALREADY_SUPPORTED',
127
+ message: 'Method "GET" is already supported. Use `overrideExisting: true` to override it.'
128
+ }
129
+ )
131
130
  })
132
131
 
133
- test('addHttpMethod does not warn when overriding an existing method explicitly', t => {
134
- const doNotWarn = () => {
135
- t.assert.fail('should not warn')
136
- }
137
- process.on('warning', doNotWarn)
138
-
132
+ test('addHttpMethod allows an explicit override of an existing method', t => {
139
133
  const fastify = Fastify()
140
134
  t.after(() => {
141
135
  fastify.close()
142
- process.removeListener('warning', doNotWarn)
143
136
  })
144
137
 
145
- fastify.addHttpMethod('POST', { overrideExisting: true })
138
+ t.assert.doesNotThrow(() => {
139
+ fastify.addHttpMethod('POST', { overrideExisting: true })
140
+ })
146
141
  })
147
142
 
148
143
  test('addHttpMethod can change an existing method body behavior', async t => {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { test } = require('node:test')
4
4
  const fastify = require('../../fastify')()
5
- fastify.addHttpMethod('TRACE')
5
+ fastify.addHttpMethod('TRACE', { overrideExisting: true })
6
6
 
7
7
  test('shorthand - trace', t => {
8
8
  t.plan(1)
@@ -5,7 +5,7 @@ const Fastify = require('../..')
5
5
  const https = require('node:https')
6
6
  const dns = require('node:dns').promises
7
7
  const { buildCertificate } = require('../build-certificate')
8
- const { Agent } = require('undici')
8
+ const { Agent, fetch } = require('undici')
9
9
 
10
10
  async function setup () {
11
11
  await buildCertificate()
@@ -5,7 +5,7 @@ const errors = require('../../lib/errors')
5
5
  const { readFileSync } = require('node:fs')
6
6
  const { resolve } = require('node:path')
7
7
 
8
- const expectedErrors = 94
8
+ const expectedErrors = 95
9
9
 
10
10
  test(`should expose ${expectedErrors} errors`, t => {
11
11
  t.plan(1)
@@ -710,6 +710,16 @@ test('FST_ERR_ROUTE_METHOD_INVALID', t => {
710
710
  t.assert.ok(error instanceof TypeError)
711
711
  })
712
712
 
713
+ test('FST_ERR_ROUTE_METHOD_ALREADY_SUPPORTED', t => {
714
+ t.plan(5)
715
+ const error = new errors.FST_ERR_ROUTE_METHOD_ALREADY_SUPPORTED('GET')
716
+ t.assert.strictEqual(error.name, 'FastifyError')
717
+ t.assert.strictEqual(error.code, 'FST_ERR_ROUTE_METHOD_ALREADY_SUPPORTED')
718
+ t.assert.strictEqual(error.message, 'Method "GET" is already supported. Use `overrideExisting: true` to override it.')
719
+ t.assert.strictEqual(error.statusCode, 500)
720
+ t.assert.ok(error instanceof TypeError)
721
+ })
722
+
713
723
  test('FST_ERR_ROUTE_METHOD_NOT_SUPPORTED', t => {
714
724
  t.plan(5)
715
725
  const error = new errors.FST_ERR_ROUTE_METHOD_NOT_SUPPORTED()
@@ -805,16 +815,16 @@ test('FST_ERR_REOPENED_SERVER', t => {
805
815
  const error = new errors.FST_ERR_REOPENED_SERVER()
806
816
  t.assert.strictEqual(error.name, 'FastifyError')
807
817
  t.assert.strictEqual(error.code, 'FST_ERR_REOPENED_SERVER')
808
- t.assert.strictEqual(error.message, 'Fastify is already listening')
818
+ t.assert.strictEqual(error.message, 'Fastify is already started')
809
819
  t.assert.strictEqual(error.statusCode, 500)
810
820
  t.assert.ok(error instanceof Error)
811
821
  })
812
822
 
813
- test('FST_ERR_INSTANCE_ALREADY_LISTENING', t => {
823
+ test('FST_ERR_INSTANCE_ALREADY_STARTED', t => {
814
824
  t.plan(5)
815
- const error = new errors.FST_ERR_INSTANCE_ALREADY_LISTENING()
825
+ const error = new errors.FST_ERR_INSTANCE_ALREADY_STARTED()
816
826
  t.assert.strictEqual(error.name, 'FastifyError')
817
- t.assert.strictEqual(error.code, 'FST_ERR_INSTANCE_ALREADY_LISTENING')
827
+ t.assert.strictEqual(error.code, 'FST_ERR_INSTANCE_ALREADY_STARTED')
818
828
  t.assert.strictEqual(error.message, 'Fastify instance is already listening. %s')
819
829
  t.assert.strictEqual(error.statusCode, 500)
820
830
  t.assert.ok(error instanceof Error)
@@ -36,20 +36,21 @@ test('without options passed to Fastify, initialConfig should expose default val
36
36
  requestTimeout: 0,
37
37
  handlerTimeout: 0,
38
38
  bodyLimit: 1024 * 1024,
39
- caseSensitive: true,
40
- allowUnsafeRegex: false,
41
- disableRequestLogging: false,
42
- ignoreTrailingSlash: false,
43
- ignoreDuplicateSlashes: false,
44
- maxParamLength: 100,
45
39
  onProtoPoisoning: 'error',
46
40
  onConstructorPoisoning: 'error',
47
41
  pluginTimeout: 10000,
48
42
  requestIdHeader: false,
49
- requestIdLogLabel: 'reqId',
50
43
  http2SessionTimeout: 72000,
51
44
  exposeHeadRoutes: true,
52
- useSemicolonDelimiter: false
45
+ routerOptions: {
46
+ allowUnsafeRegex: false,
47
+ caseSensitive: true,
48
+ constraints: undefined,
49
+ ignoreTrailingSlash: false,
50
+ ignoreDuplicateSlashes: false,
51
+ maxParamLength: 100,
52
+ useSemicolonDelimiter: false
53
+ }
53
54
  }
54
55
 
55
56
  t.assert.deepStrictEqual(Fastify().initialConfig, fastifyDefaultOptions)
@@ -88,65 +89,79 @@ test('Fastify.initialConfig should expose all options', t => {
88
89
  key: global.context.key,
89
90
  cert: global.context.cert
90
91
  },
91
- ignoreTrailingSlash: true,
92
- ignoreDuplicateSlashes: true,
93
- maxParamLength: 200,
94
92
  connectionTimeout: 0,
95
93
  keepAliveTimeout: 72000,
96
94
  bodyLimit: 1049600,
97
95
  onProtoPoisoning: 'remove',
98
96
  serverFactory,
99
- caseSensitive: true,
100
- allowUnsafeRegex: false,
101
97
  requestIdHeader: 'request-id-alt',
102
98
  pluginTimeout: 20000,
103
- useSemicolonDelimiter: false,
104
- querystringParser: str => str,
105
99
  genReqId: function (req) {
106
100
  return reqId++
107
101
  },
108
102
  loggerInstance: pino({ level: 'info' }),
109
- constraints: {
110
- version: versionStrategy
111
- },
112
103
  trustProxy: function myTrustFn (address, hop) {
113
104
  return address === '1.2.3.4' || hop === 1
105
+ },
106
+ routerOptions: {
107
+ allowUnsafeRegex: false,
108
+ caseSensitive: true,
109
+ constraints: {
110
+ version: versionStrategy
111
+ },
112
+ ignoreTrailingSlash: true,
113
+ ignoreDuplicateSlashes: true,
114
+ maxParamLength: 200,
115
+ querystringParser: str => str,
116
+ useSemicolonDelimiter: false
114
117
  }
115
118
  }
116
119
 
117
120
  const fastify = Fastify(options)
121
+
118
122
  t.assert.strictEqual(fastify.initialConfig.http2, true)
119
123
  t.assert.strictEqual(fastify.initialConfig.https, true, 'for security reason the key cert is hidden')
120
- t.assert.strictEqual(fastify.initialConfig.ignoreTrailingSlash, true)
121
- t.assert.strictEqual(fastify.initialConfig.ignoreDuplicateSlashes, true)
122
- t.assert.strictEqual(fastify.initialConfig.maxParamLength, 200)
123
124
  t.assert.strictEqual(fastify.initialConfig.connectionTimeout, 0)
124
125
  t.assert.strictEqual(fastify.initialConfig.keepAliveTimeout, 72000)
125
126
  t.assert.strictEqual(fastify.initialConfig.bodyLimit, 1049600)
126
127
  t.assert.strictEqual(fastify.initialConfig.onProtoPoisoning, 'remove')
127
- t.assert.strictEqual(fastify.initialConfig.caseSensitive, true)
128
- t.assert.strictEqual(fastify.initialConfig.useSemicolonDelimiter, false)
129
- t.assert.strictEqual(fastify.initialConfig.allowUnsafeRegex, false)
130
128
  t.assert.strictEqual(fastify.initialConfig.requestIdHeader, 'request-id-alt')
131
129
  t.assert.strictEqual(fastify.initialConfig.pluginTimeout, 20000)
132
- t.assert.ok(fastify.initialConfig.constraints.version)
133
130
 
134
131
  // obfuscated options:
135
132
  t.assert.strictEqual(fastify.initialConfig.serverFactory, undefined)
136
133
  t.assert.strictEqual(fastify.initialConfig.trustProxy, undefined)
137
134
  t.assert.strictEqual(fastify.initialConfig.genReqId, undefined)
138
135
  t.assert.strictEqual(fastify.initialConfig.childLoggerFactory, undefined)
139
- t.assert.strictEqual(fastify.initialConfig.querystringParser, undefined)
140
136
  t.assert.strictEqual(fastify.initialConfig.logger, undefined)
141
137
  t.assert.strictEqual(fastify.initialConfig.trustProxy, undefined)
138
+
139
+ // router options
140
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.allowUnsafeRegex, false)
141
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.caseSensitive, true)
142
+ t.assert.ok(fastify.initialConfig.routerOptions.constraints.version)
143
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.ignoreTrailingSlash, true)
144
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.ignoreDuplicateSlashes, true)
145
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.maxParamLength, 200)
146
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.querystringParser, undefined)
147
+ t.assert.strictEqual(fastify.initialConfig.routerOptions.useSemicolonDelimiter, false)
142
148
  })
143
149
 
144
150
  test('Should throw if you try to modify Fastify.initialConfig', t => {
145
- t.plan(4)
151
+ t.plan(8)
146
152
 
147
- const fastify = Fastify({ ignoreTrailingSlash: true })
153
+ const fastify = Fastify({ keepAliveTimeout: 1, routerOptions: { ignoreTrailingSlash: true } })
148
154
  try {
149
- fastify.initialConfig.ignoreTrailingSlash = false
155
+ fastify.initialConfig.keepAliveTimeout = 2
156
+ t.assert.fail()
157
+ } catch (error) {
158
+ t.assert.ok(error instanceof TypeError)
159
+ t.assert.strictEqual(error.message, "Cannot assign to read only property 'keepAliveTimeout' of object '#<Object>'")
160
+ t.assert.ok(error.stack)
161
+ t.assert.ok(true)
162
+ }
163
+ try {
164
+ fastify.initialConfig.routerOptions.ignoreTrailingSlash = false
150
165
  t.assert.fail()
151
166
  } catch (error) {
152
167
  t.assert.ok(error instanceof TypeError)
@@ -252,10 +267,12 @@ test('Should not have issues when passing stream options to Pino.js', (t, done)
252
267
  const stream = split(JSON.parse)
253
268
 
254
269
  const originalOptions = {
255
- ignoreTrailingSlash: true,
256
270
  logger: {
257
271
  level: 'trace',
258
272
  stream
273
+ },
274
+ routerOptions: {
275
+ ignoreTrailingSlash: true
259
276
  }
260
277
  }
261
278
 
@@ -276,20 +293,21 @@ test('Should not have issues when passing stream options to Pino.js', (t, done)
276
293
  requestTimeout: 0,
277
294
  handlerTimeout: 0,
278
295
  bodyLimit: 1024 * 1024,
279
- caseSensitive: true,
280
- allowUnsafeRegex: false,
281
- disableRequestLogging: false,
282
- ignoreTrailingSlash: true,
283
- ignoreDuplicateSlashes: false,
284
- maxParamLength: 100,
285
296
  onProtoPoisoning: 'error',
286
297
  onConstructorPoisoning: 'error',
287
298
  pluginTimeout: 10000,
288
299
  requestIdHeader: false,
289
- requestIdLogLabel: 'reqId',
290
300
  http2SessionTimeout: 72000,
291
301
  exposeHeadRoutes: true,
292
- useSemicolonDelimiter: false
302
+ routerOptions: {
303
+ allowUnsafeRegex: false,
304
+ caseSensitive: true,
305
+ constraints: undefined,
306
+ ignoreTrailingSlash: true,
307
+ ignoreDuplicateSlashes: false,
308
+ maxParamLength: 100,
309
+ useSemicolonDelimiter: false
310
+ }
293
311
  })
294
312
  } catch (error) {
295
313
  t.assert.fail()