fastify 3.25.3 → 3.27.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 (60) hide show
  1. package/LICENSE +1 -1
  2. package/build/build-validation.js +2 -0
  3. package/docs/Guides/Ecosystem.md +2 -1
  4. package/docs/Guides/Index.md +2 -0
  5. package/docs/Guides/Prototype-Poisoning.md +391 -0
  6. package/docs/Guides/Recommendations.md +1 -1
  7. package/docs/Reference/ContentTypeParser.md +4 -1
  8. package/docs/Reference/Plugins.md +4 -4
  9. package/docs/Reference/Request.md +3 -0
  10. package/docs/Reference/Server.md +52 -2
  11. package/docs/Reference/TypeScript.md +1 -1
  12. package/docs/Reference/Validation-and-Serialization.md +4 -1
  13. package/fastify.d.ts +3 -1
  14. package/fastify.js +41 -21
  15. package/lib/decorate.js +2 -2
  16. package/lib/errors.js +6 -1
  17. package/lib/noop-set.js +10 -0
  18. package/lib/pluginUtils.js +5 -0
  19. package/lib/reply.js +21 -11
  20. package/lib/route.js +34 -1
  21. package/lib/schema-controller.js +1 -1
  22. package/lib/server.js +1 -1
  23. package/lib/symbols.js +3 -1
  24. package/package.json +16 -17
  25. package/test/404s.test.js +25 -1
  26. package/test/async-await.test.js +3 -3
  27. package/test/bundler/esbuild/bundler-test.js +31 -0
  28. package/test/bundler/esbuild/package.json +10 -0
  29. package/test/bundler/esbuild/src/fail-plugin-version.js +12 -0
  30. package/test/bundler/esbuild/src/index.js +7 -0
  31. package/test/bundler/webpack/bundler-test.js +15 -4
  32. package/test/bundler/webpack/src/fail-plugin-version.js +1 -3
  33. package/test/bundler/webpack/src/index.js +1 -3
  34. package/test/close.test.js +39 -1
  35. package/test/context-config.test.js +4 -4
  36. package/test/custom-parser.test.js +30 -31
  37. package/test/inject.test.js +1 -1
  38. package/test/internals/all.test.js +2 -2
  39. package/test/internals/contentTypeParser.test.js +4 -4
  40. package/test/internals/handleRequest.test.js +8 -8
  41. package/test/internals/logger.test.js +1 -1
  42. package/test/logger.test.js +18 -18
  43. package/test/maxRequestsPerSocket.test.js +2 -2
  44. package/test/noop-set.test.js +19 -0
  45. package/test/plugin.name.display.js +10 -0
  46. package/test/plugin.test.js +18 -0
  47. package/test/route.test.js +12 -0
  48. package/test/schema-serialization.test.js +41 -0
  49. package/test/skip-reply-send.test.js +7 -7
  50. package/test/trust-proxy.test.js +1 -1
  51. package/test/types/fastify.test-d.ts +18 -0
  52. package/test/types/hooks.test-d.ts +34 -6
  53. package/test/types/instance.test-d.ts +26 -1
  54. package/test/validation-error-handling.test.js +1 -1
  55. package/test/versioned-routes.test.js +28 -4
  56. package/types/.eslintrc.json +1 -1
  57. package/types/hooks.d.ts +24 -20
  58. package/types/instance.d.ts +13 -1
  59. package/types/register.d.ts +1 -1
  60. package/types/schema.d.ts +14 -0
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '3.25.3'
3
+ const VERSION = '3.27.2'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('http')
@@ -16,6 +16,7 @@ const {
16
16
  kLogSerializers,
17
17
  kHooks,
18
18
  kSchemaController,
19
+ kRequestAcceptVersion,
19
20
  kReplySerializerDefault,
20
21
  kContentTypeParser,
21
22
  kReply,
@@ -25,7 +26,9 @@ const {
25
26
  kOptions,
26
27
  kPluginNameChain,
27
28
  kSchemaErrorFormatter,
28
- kErrorHandler
29
+ kErrorHandler,
30
+ kKeepAliveConnections,
31
+ kFourOhFourContext
29
32
  } = require('./lib/symbols.js')
30
33
 
31
34
  const { createServer } = require('./lib/server')
@@ -44,6 +47,7 @@ const build404 = require('./lib/fourOhFour')
44
47
  const getSecuredInitialConfig = require('./lib/initialConfigValidation')
45
48
  const override = require('./lib/pluginOverride')
46
49
  const warning = require('./lib/warnings')
50
+ const noopSet = require('./lib/noop-set')
47
51
  const { defaultInitOptions } = getSecuredInitialConfig
48
52
 
49
53
  const {
@@ -55,7 +59,8 @@ const onBadUrlContext = {
55
59
  config: {
56
60
  },
57
61
  onSend: [],
58
- onError: []
62
+ onError: [],
63
+ [kFourOhFourContext]: null
59
64
  }
60
65
 
61
66
  function defaultBuildPrettyMeta (route) {
@@ -132,6 +137,7 @@ function fastify (options) {
132
137
  // Update the options with the fixed values
133
138
  options.connectionTimeout = options.connectionTimeout || defaultInitOptions.connectionTimeout
134
139
  options.keepAliveTimeout = options.keepAliveTimeout || defaultInitOptions.keepAliveTimeout
140
+ options.forceCloseConnections = typeof options.forceCloseConnections === 'boolean' ? options.forceCloseConnections : defaultInitOptions.forceCloseConnections
135
141
  options.maxRequestsPerSocket = options.maxRequestsPerSocket || defaultInitOptions.maxRequestsPerSocket
136
142
  options.requestTimeout = options.requestTimeout || defaultInitOptions.requestTimeout
137
143
  options.logger = logger
@@ -145,6 +151,7 @@ function fastify (options) {
145
151
  options.exposeHeadRoutes = exposeHeadRoutes
146
152
 
147
153
  const initialConfig = getSecuredInitialConfig(options)
154
+ const keepAliveConnections = options.forceCloseConnections === true ? new Set() : noopSet()
148
155
 
149
156
  let constraints = options.constraints
150
157
  if (options.versioning) {
@@ -168,14 +175,15 @@ function fastify (options) {
168
175
  // Default router
169
176
  const router = buildRouting({
170
177
  config: {
171
- defaultRoute: defaultRoute,
172
- onBadUrl: onBadUrl,
173
- constraints: constraints,
178
+ defaultRoute,
179
+ onBadUrl,
180
+ constraints,
174
181
  ignoreTrailingSlash: options.ignoreTrailingSlash || defaultInitOptions.ignoreTrailingSlash,
175
182
  maxParamLength: options.maxParamLength || defaultInitOptions.maxParamLength,
176
183
  caseSensitive: options.caseSensitive,
177
184
  buildPrettyMeta: defaultBuildPrettyMeta
178
- }
185
+ },
186
+ keepAliveConnections
179
187
  })
180
188
 
181
189
  // 404 router, used for handling encapsulated 404 handlers
@@ -199,6 +207,7 @@ function fastify (options) {
199
207
  closing: false,
200
208
  started: false
201
209
  },
210
+ [kKeepAliveConnections]: keepAliveConnections,
202
211
  [kOptions]: options,
203
212
  [kChildren]: [],
204
213
  [kBodyLimit]: bodyLimit,
@@ -259,16 +268,16 @@ function fastify (options) {
259
268
  // expose logger instance
260
269
  log: logger,
261
270
  // hooks
262
- addHook: addHook,
271
+ addHook,
263
272
  // schemas
264
- addSchema: addSchema,
273
+ addSchema,
265
274
  getSchema: schemaController.getSchema.bind(schemaController),
266
275
  getSchemas: schemaController.getSchemas.bind(schemaController),
267
- setValidatorCompiler: setValidatorCompiler,
268
- setSerializerCompiler: setSerializerCompiler,
269
- setSchemaController: setSchemaController,
270
- setReplySerializer: setReplySerializer,
271
- setSchemaErrorFormatter: setSchemaErrorFormatter,
276
+ setValidatorCompiler,
277
+ setSerializerCompiler,
278
+ setSchemaController,
279
+ setReplySerializer,
280
+ setSchemaErrorFormatter,
272
281
  // custom parsers
273
282
  addContentTypeParser: ContentTypeParser.helpers.addContentTypeParser,
274
283
  hasContentTypeParser: ContentTypeParser.helpers.hasContentTypeParser,
@@ -284,8 +293,8 @@ function fastify (options) {
284
293
  close: null,
285
294
  printPlugins: null,
286
295
  // http server
287
- listen: listen,
288
- server: server,
296
+ listen,
297
+ server,
289
298
  // extend fastify objects
290
299
  decorate: decorator.add,
291
300
  hasDecorator: decorator.exist,
@@ -294,12 +303,12 @@ function fastify (options) {
294
303
  hasRequestDecorator: decorator.existRequest,
295
304
  hasReplyDecorator: decorator.existReply,
296
305
  // fake http injection
297
- inject: inject,
306
+ inject,
298
307
  // pretty print of the registered routes
299
308
  printRoutes,
300
309
  // custom error handling
301
- setNotFoundHandler: setNotFoundHandler,
302
- setErrorHandler: setErrorHandler,
310
+ setNotFoundHandler,
311
+ setErrorHandler,
303
312
  // Set fastify initial configuration options read-only object
304
313
  initialConfig
305
314
  }
@@ -374,6 +383,15 @@ function fastify (options) {
374
383
  if (fastify[kState].listening) {
375
384
  // No new TCP connections are accepted
376
385
  instance.server.close(done)
386
+
387
+ for (const conn of fastify[kKeepAliveConnections]) {
388
+ // We must invoke the destroy method instead of merely unreffing
389
+ // the sockets. If we only unref, then the callback passed to
390
+ // `fastify.close` will never be invoked; nor will any of the
391
+ // registered `onClose` hooks.
392
+ conn.destroy()
393
+ fastify[kKeepAliveConnections].delete(conn)
394
+ }
377
395
  } else {
378
396
  done(null)
379
397
  }
@@ -520,10 +538,8 @@ function fastify (options) {
520
538
  }
521
539
 
522
540
  if (name === 'onClose') {
523
- this[kHooks].validate(name, fn)
524
541
  this.onClose(fn)
525
542
  } else if (name === 'onReady') {
526
- this[kHooks].validate(name, fn)
527
543
  this[kHooks].add(name, fn)
528
544
  } else {
529
545
  this.after((err, done) => {
@@ -578,6 +594,10 @@ function fastify (options) {
578
594
  // req and res are Node.js core objects
579
595
  function defaultRoute (req, res) {
580
596
  if (req.headers['accept-version'] !== undefined) {
597
+ // we remove the accept-version header for performance result
598
+ // because we do not want to go through the constraint checking
599
+ // the usage of symbol here to prevent any colision on custom header name
600
+ req.headers[kRequestAcceptVersion] = req.headers['accept-version']
581
601
  req.headers['accept-version'] = undefined
582
602
  }
583
603
  fourOhFour.router.lookup(req, res)
package/lib/decorate.js CHANGED
@@ -134,6 +134,6 @@ module.exports = {
134
134
  existRequest: checkRequestExistence,
135
135
  existReply: checkReplyExistence,
136
136
  dependencies: checkDependencies,
137
- decorateReply: decorateReply,
138
- decorateRequest: decorateRequest
137
+ decorateReply,
138
+ decorateRequest
139
139
  }
package/lib/errors.js CHANGED
@@ -106,7 +106,7 @@ const codes = {
106
106
  */
107
107
  FST_ERR_MISSING_MIDDLEWARE: createError(
108
108
  'FST_ERR_MISSING_MIDDLEWARE',
109
- 'You must register a plugin for handling middlewares, visit fastify.io/docs/latest/Middleware/ for more info.',
109
+ 'You must register a plugin for handling middlewares, visit fastify.io/docs/latest/Reference/Middleware/ for more info.',
110
110
  500
111
111
  ),
112
112
 
@@ -210,6 +210,11 @@ const codes = {
210
210
  500,
211
211
  TypeError
212
212
  ),
213
+ FST_ERR_INVALID_URL: createError(
214
+ 'FST_ERR_INVALID_URL',
215
+ "URL must be a string. Received '%s'",
216
+ 400
217
+ ),
213
218
 
214
219
  /**
215
220
  * again listen when close server
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ module.exports = function noopSet () {
4
+ return {
5
+ [Symbol.iterator]: function * () {},
6
+ add () {},
7
+ delete () {},
8
+ has () { return true }
9
+ }
10
+ }
@@ -14,6 +14,11 @@ function getMeta (fn) {
14
14
  }
15
15
 
16
16
  function getPluginName (func) {
17
+ const display = getDisplayName(func)
18
+ if (display) {
19
+ return display
20
+ }
21
+
17
22
  // let's see if this is a file, and in that case use that
18
23
  // this is common for plugins
19
24
  const cache = require.cache
package/lib/reply.js CHANGED
@@ -365,12 +365,18 @@ function preserializeHookEnd (err, request, reply, payload) {
365
365
  return
366
366
  }
367
367
 
368
- if (reply[kReplySerializer] !== null) {
369
- payload = reply[kReplySerializer](payload)
370
- } else if (reply.context && reply.context[kReplySerializerDefault]) {
371
- payload = reply.context[kReplySerializerDefault](payload, reply.raw.statusCode)
372
- } else {
373
- payload = serialize(reply.context, payload, reply.raw.statusCode)
368
+ try {
369
+ if (reply[kReplySerializer] !== null) {
370
+ payload = reply[kReplySerializer](payload)
371
+ } else if (reply.context && reply.context[kReplySerializerDefault]) {
372
+ payload = reply.context[kReplySerializerDefault](payload, reply.raw.statusCode)
373
+ } else {
374
+ payload = serialize(reply.context, payload, reply.raw.statusCode)
375
+ }
376
+ } catch (e) {
377
+ wrapSeralizationError(e, reply)
378
+ onErrorHook(reply, e)
379
+ return
374
380
  }
375
381
 
376
382
  flatstr(payload)
@@ -378,6 +384,10 @@ function preserializeHookEnd (err, request, reply, payload) {
378
384
  onSendHook(reply, payload)
379
385
  }
380
386
 
387
+ function wrapSeralizationError (error, reply) {
388
+ error.serialization = reply.context.config
389
+ }
390
+
381
391
  function onSendHook (reply, payload) {
382
392
  if (reply.context.onSend !== null) {
383
393
  reply[kReplySent] = true
@@ -569,11 +579,11 @@ function handleError (reply, error, cb) {
569
579
  const serializerFn = getSchemaSerializer(reply.context, statusCode)
570
580
  payload = (serializerFn === false)
571
581
  ? serializeError({
572
- error: statusCodes[statusCode + ''],
573
- code: error.code,
574
- message: error.message || '',
575
- statusCode: statusCode
576
- })
582
+ error: statusCodes[statusCode + ''],
583
+ code: error.code,
584
+ message: error.message || '',
585
+ statusCode
586
+ })
577
587
  : serializerFn(Object.create(error, {
578
588
  error: { value: statusCodes[statusCode + ''] },
579
589
  message: { value: error.message || '' },
package/lib/route.js CHANGED
@@ -8,6 +8,7 @@ const supportedMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTI
8
8
  const { normalizeSchema } = require('./schemas')
9
9
  const { parseHeadOnSendHandlers } = require('./headRoute')
10
10
  const warning = require('./warnings')
11
+ const { kRequestAcceptVersion } = require('./symbols')
11
12
 
12
13
  const {
13
14
  compileSchemasForValidation,
@@ -17,7 +18,8 @@ const {
17
18
  const {
18
19
  FST_ERR_SCH_VALIDATION_BUILD,
19
20
  FST_ERR_SCH_SERIALIZATION_BUILD,
20
- FST_ERR_DEFAULT_ROUTE_INVALID_TYPE
21
+ FST_ERR_DEFAULT_ROUTE_INVALID_TYPE,
22
+ FST_ERR_INVALID_URL
21
23
  } = require('./errors')
22
24
 
23
25
  const {
@@ -40,6 +42,7 @@ const {
40
42
  } = require('./symbols.js')
41
43
 
42
44
  function buildRouting (options) {
45
+ const { keepAliveConnections } = options
43
46
  const router = FindMyWay(options.config)
44
47
 
45
48
  let avvio
@@ -97,6 +100,10 @@ function buildRouting (options) {
97
100
 
98
101
  // Convert shorthand to extended route declaration
99
102
  function prepareRoute (method, url, options, handler) {
103
+ if (typeof url !== 'string') {
104
+ throw new FST_ERR_INVALID_URL(typeof url)
105
+ }
106
+
100
107
  if (!handler && typeof options === 'function') {
101
108
  handler = options // for support over direct function calls such as fastify.get() options are reused as the handler
102
109
  options = {}
@@ -344,6 +351,23 @@ function buildRouting (options) {
344
351
  }
345
352
  }
346
353
 
354
+ // When server.forceCloseConnections is true, we will collect any requests
355
+ // that have indicated they want persistence so that they can be reaped
356
+ // on server close. Otherwise, the container is a noop container.
357
+ const connHeader = String.prototype.toLowerCase.call(req.headers.connection || '')
358
+ if (connHeader === 'keep-alive') {
359
+ if (keepAliveConnections.has(req.socket) === false) {
360
+ keepAliveConnections.add(req.socket)
361
+ req.socket.on('close', removeTrackedSocket.bind({ keepAliveConnections, socket: req.socket }))
362
+ }
363
+ }
364
+
365
+ // we revert the changes in defaultRoute
366
+ if (req.headers[kRequestAcceptVersion] !== undefined) {
367
+ req.headers['accept-version'] = req.headers[kRequestAcceptVersion]
368
+ req.headers[kRequestAcceptVersion] = undefined
369
+ }
370
+
347
371
  const id = req.headers[requestIdHeader] || genReqId(req)
348
372
 
349
373
  const loggerBinding = {
@@ -478,6 +502,15 @@ function preParsingHookRunner (functions, request, reply, cb) {
478
502
  next(null, request[kRequestPayloadStream])
479
503
  }
480
504
 
505
+ /**
506
+ * Used within the route handler as a `net.Socket.close` event handler.
507
+ * The purpose is to remove a socket from the tracked sockets collection when
508
+ * the socket has naturally timed out.
509
+ */
510
+ function removeTrackedSocket () {
511
+ this.keepAliveConnections.delete(this.socket)
512
+ }
513
+
481
514
  function noop () { }
482
515
 
483
516
  module.exports = { buildRouting, validateBodyLimitOption }
@@ -25,7 +25,7 @@ function buildSchemaController (parentSchemaCtrl, opts) {
25
25
 
26
26
  const option = {
27
27
  bucket: (opts && opts.bucket) || buildSchemas,
28
- compilersFactory: compilersFactory
28
+ compilersFactory
29
29
  }
30
30
 
31
31
  return new SchemaController(undefined, option)
package/lib/server.js CHANGED
@@ -52,7 +52,7 @@ function createServer (options, httpHandler) {
52
52
  }
53
53
 
54
54
  const cb = typeof args[args.length - 1] === 'function' ? args.pop() : undefined
55
- const options = { cb: cb }
55
+ const options = { cb }
56
56
 
57
57
  const firstArg = args[0]
58
58
  const argsLength = args.length
package/lib/symbols.js CHANGED
@@ -21,6 +21,7 @@ const keys = {
21
21
  kReply: Symbol('fastify.Reply'),
22
22
  kRequest: Symbol('fastify.Request'),
23
23
  kRequestPayloadStream: Symbol('fastify.RequestPayloadStream'),
24
+ kRequestAcceptVersion: Symbol('fastify.RequestAcceptVersion'),
24
25
  kCanSetNotFoundHandler: Symbol('fastify.canSetNotFoundHandler'),
25
26
  kFourOhFour: Symbol('fastify.404'),
26
27
  kFourOhFourLevelInstance: Symbol('fastify.404LogLevelInstance'),
@@ -43,7 +44,8 @@ const keys = {
43
44
  kPluginNameChain: Symbol('fastify.pluginNameChain'),
44
45
  // This symbol is only meant to be used for fastify tests and should not be used for any other purpose
45
46
  kTestInternals: Symbol('fastify.testInternals'),
46
- kErrorHandler: Symbol('fastify.errorHandler')
47
+ kErrorHandler: Symbol('fastify.errorHandler'),
48
+ kKeepAliveConnections: Symbol('fastify.keepAliveConnections')
47
49
  }
48
50
 
49
51
  module.exports = keys
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "3.25.3",
3
+ "version": "3.27.2",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -12,11 +12,11 @@
12
12
  "license-checker": "license-checker --production --onlyAllow=\"MIT;ISC;BSD-3-Clause;BSD-2-Clause\"",
13
13
  "lint": "npm run lint:standard && npm run lint:typescript",
14
14
  "lint:fix": "standard --fix",
15
- "lint:standard": "standard --verbose | snazzy",
15
+ "lint:standard": "standard | snazzy",
16
16
  "lint:typescript": "eslint -c types/.eslintrc.json types/**/*.d.ts test/types/**/*.test-d.ts",
17
17
  "prepublishOnly": "tap --no-check-coverage test/internals/version.test.js",
18
18
  "test": "npm run lint && npm run unit && npm run test:typescript",
19
- "test:ci": "npm run lint && npm run unit -- --cov --coverage-report=lcovonly && npm run test:typescript",
19
+ "test:ci": "npm run unit -- -R terse --cov --coverage-report=lcovonly && npm run test:typescript",
20
20
  "test:report": "npm run lint && npm run unit:report && npm run test:typescript",
21
21
  "test:typescript": "tsd",
22
22
  "unit": "tap -J test/*.test.js test/*/*.test.js",
@@ -124,11 +124,12 @@
124
124
  "@fastify/ajv-compiler-8": "npm:@fastify/ajv-compiler@^2.0.0",
125
125
  "@fastify/pre-commit": "^2.0.1",
126
126
  "@hapi/joi": "^17.1.1",
127
- "@sinonjs/fake-timers": "^8.1.0",
127
+ "@sinonjs/fake-timers": "^9.1.0",
128
128
  "@types/node": "^16.0.0",
129
129
  "@types/pino": "^6.0.1",
130
- "@typescript-eslint/eslint-plugin": "^4.5.0",
131
- "@typescript-eslint/parser": "^4.5.0",
130
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
131
+ "@typescript-eslint/parser": "^5.0.0",
132
+ "JSONStream": "^1.3.5",
132
133
  "ajv": "^6.0.0",
133
134
  "ajv-errors": "^1.0.1",
134
135
  "ajv-formats": "^2.1.1",
@@ -139,25 +140,23 @@
139
140
  "cors": "^2.8.5",
140
141
  "coveralls": "^3.1.0",
141
142
  "dns-prefetch-control": "^0.3.0",
142
- "eslint": "^7.11.0",
143
- "eslint-config-standard": "^16.0.1",
143
+ "eslint": "^8.0.1",
144
+ "eslint-config-standard": "^17.0.0-1",
144
145
  "eslint-import-resolver-node": "^0.3.2",
145
- "eslint-plugin-import": "^2.20.2",
146
- "eslint-plugin-node": "^11.1.0",
147
- "eslint-plugin-promise": "^5.1.0",
148
- "eslint-plugin-standard": "^5.0.0",
146
+ "eslint-plugin-import": "^2.25.4",
147
+ "eslint-plugin-n": "^14.0.0",
148
+ "eslint-plugin-promise": "^6.0.0",
149
149
  "fast-json-body": "^1.1.0",
150
150
  "fastify-plugin": "^3.0.0",
151
151
  "fluent-json-schema": "^3.0.0",
152
152
  "form-data": "^4.0.0",
153
153
  "frameguard": "^4.0.0",
154
154
  "h2url": "^0.2.0",
155
- "helmet": "^4.0.0",
155
+ "helmet": "^5.0.1",
156
156
  "hide-powered-by": "^1.1.0",
157
157
  "hsts": "^2.2.0",
158
158
  "http-errors": "^2.0.0",
159
159
  "ienoopen": "^1.1.0",
160
- "JSONStream": "^1.3.5",
161
160
  "license-checker": "^25.0.1",
162
161
  "pem": "^1.14.4",
163
162
  "proxyquire": "^2.1.3",
@@ -167,13 +166,13 @@
167
166
  "simple-get": "^4.0.0",
168
167
  "snazzy": "^9.0.0",
169
168
  "split2": "^4.1.0",
170
- "standard": "^16.0.1",
169
+ "standard": "^17.0.0-2",
171
170
  "tap": "^15.1.1",
172
171
  "tap-mocha-reporter": "^5.0.1",
173
172
  "then-sleep": "^1.0.1",
174
173
  "tsd": "^0.19.0",
175
174
  "typescript": "^4.0.2",
176
- "undici": "^3.3.5",
175
+ "undici": "^3.3.6",
177
176
  "x-xss-protection": "^2.0.0",
178
177
  "yup": "^0.32.0"
179
178
  },
@@ -192,7 +191,7 @@
192
191
  "rfdc": "^1.1.4",
193
192
  "secure-json-parse": "^2.0.0",
194
193
  "semver": "^7.3.2",
195
- "tiny-lru": "^7.0.0"
194
+ "tiny-lru": "^8.0.1"
196
195
  },
197
196
  "standard": {
198
197
  "ignore": [
package/test/404s.test.js CHANGED
@@ -1221,7 +1221,7 @@ test('preHandler option for setNotFoundHandler', t => {
1221
1221
  })
1222
1222
 
1223
1223
  // https://github.com/fastify/fastify/issues/2229
1224
- t.test('preHandler hook in setNotFoundHandler should be called when callNotFound', t => {
1224
+ t.test('preHandler hook in setNotFoundHandler should be called when callNotFound', { timeout: 40000 }, t => {
1225
1225
  t.plan(2)
1226
1226
  const fastify = Fastify()
1227
1227
 
@@ -1772,3 +1772,27 @@ test('setNotFoundHandler should be chaining fastify instance', t => {
1772
1772
 
1773
1773
  t.end()
1774
1774
  })
1775
+
1776
+ test('Send 404 when frameworkError calls reply.callNotFound', t => {
1777
+ t.test('Dynamic route', t => {
1778
+ t.plan(4)
1779
+ const fastify = Fastify({
1780
+ logger: true,
1781
+ frameworkErrors: (error, req, reply) => {
1782
+ t.equal(error.message, "'%world' is not a valid url component")
1783
+ return reply.callNotFound()
1784
+ }
1785
+ })
1786
+ fastify.get('/hello/:id', () => t.fail('we should not be here'))
1787
+ fastify.inject({
1788
+ url: '/hello/%world',
1789
+ method: 'GET'
1790
+ }, (err, response) => {
1791
+ t.error(err)
1792
+ t.equal(response.statusCode, 404)
1793
+ t.equal(response.payload, '404 Not Found')
1794
+ })
1795
+ })
1796
+
1797
+ t.end()
1798
+ })
@@ -407,7 +407,7 @@ test('error is logged because promise was fulfilled with undefined', t => {
407
407
  try {
408
408
  fastify = Fastify({
409
409
  logger: {
410
- stream: stream,
410
+ stream,
411
411
  level: 'error'
412
412
  }
413
413
  })
@@ -447,7 +447,7 @@ test('error is not logged because promise was fulfilled with undefined but statu
447
447
  try {
448
448
  fastify = Fastify({
449
449
  logger: {
450
- stream: stream,
450
+ stream,
451
451
  level: 'error'
452
452
  }
453
453
  })
@@ -488,7 +488,7 @@ test('error is not logged because promise was fulfilled with undefined but respo
488
488
  try {
489
489
  fastify = Fastify({
490
490
  logger: {
491
- stream: stream,
491
+ stream,
492
492
  level: 'error'
493
493
  }
494
494
  })
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const test = t.test
5
+ const fastifySuccess = require('./dist/success')
6
+ const fastifyFailPlugin = require('./dist/failPlugin')
7
+
8
+ test('Bundled package should work', (t) => {
9
+ t.plan(4)
10
+ fastifySuccess.ready((err) => {
11
+ t.error(err)
12
+ fastifySuccess.inject(
13
+ {
14
+ method: 'GET',
15
+ url: '/'
16
+ },
17
+ (error, res) => {
18
+ t.error(error)
19
+ t.equal(res.statusCode, 200)
20
+ t.same(res.json(), { hello: 'world' })
21
+ }
22
+ )
23
+ })
24
+ })
25
+
26
+ test('Bundled package should not work with bad plugin version', (t) => {
27
+ t.plan(1)
28
+ fastifyFailPlugin.ready((err) => {
29
+ t.match(err.message, /expected '9.x' fastify version/i)
30
+ })
31
+ })
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": "0.0.1",
3
+ "scripts": {
4
+ "bundle": "esbuild success=src/index.js failPlugin=src/fail-plugin-version.js --bundle --outdir=dist --platform=node",
5
+ "test": "npm run bundle && node bundler-test.js"
6
+ },
7
+ "devDependencies": {
8
+ "esbuild": "^0.14.11"
9
+ }
10
+ }
@@ -0,0 +1,12 @@
1
+ const fp = require('fastify-plugin')
2
+ const fastify = require('../../../../')()
3
+
4
+ fastify.get('/', function (request, reply) {
5
+ reply.send({ hello: 'world' })
6
+ })
7
+
8
+ fastify.register(fp((instance, opts, done) => {
9
+ done()
10
+ }, { fastify: '9.x' }))
11
+
12
+ module.exports = fastify
@@ -0,0 +1,7 @@
1
+ const fastify = require('../../../../')()
2
+ // Declare a route
3
+ fastify.get('/', function (request, reply) {
4
+ reply.send({ hello: 'world' })
5
+ })
6
+
7
+ module.exports = fastify
@@ -5,16 +5,27 @@ const test = t.test
5
5
  const fastifySuccess = require('./dist/success')
6
6
  const fastifyFailPlugin = require('./dist/failPlugin')
7
7
 
8
- test('Bundled package should work', t => {
9
- t.plan(1)
8
+ test('Bundled package should work', (t) => {
9
+ t.plan(4)
10
10
  fastifySuccess.ready((err) => {
11
11
  t.error(err)
12
+ fastifySuccess.inject(
13
+ {
14
+ method: 'GET',
15
+ url: '/'
16
+ },
17
+ (error, res) => {
18
+ t.error(error)
19
+ t.equal(res.statusCode, 200)
20
+ t.same(res.json(), { hello: 'world' })
21
+ }
22
+ )
12
23
  })
13
24
  })
14
25
 
15
- test('Bundled package should not work with bad plugin version', t => {
26
+ test('Bundled package should not work with bad plugin version', (t) => {
16
27
  t.plan(1)
17
28
  fastifyFailPlugin.ready((err) => {
18
- t.ok(err)
29
+ t.match(err.message, /expected '9.x' fastify version/i)
19
30
  })
20
31
  })
@@ -1,7 +1,5 @@
1
1
  const fp = require('fastify-plugin')
2
- const fastify = require('../../../../')({
3
- logger: true
4
- })
2
+ const fastify = require('../../../../')()
5
3
 
6
4
  fastify.get('/', function (request, reply) {
7
5
  reply.send({ hello: 'world' })
@@ -1,6 +1,4 @@
1
- const fastify = require('../../../../')({
2
- logger: true
3
- })
1
+ const fastify = require('../../../../')()
4
2
  // Declare a route
5
3
  fastify.get('/', function (request, reply) {
6
4
  reply.send({ hello: 'world' })