fastify 5.6.2 → 5.7.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 +34 -33
  2. package/SECURITY.md +45 -7
  3. package/SPONSORS.md +1 -1
  4. package/build/build-validation.js +1 -2
  5. package/build/sync-version.js +0 -1
  6. package/docs/Guides/Detecting-When-Clients-Abort.md +1 -1
  7. package/docs/Guides/Ecosystem.md +12 -15
  8. package/docs/Guides/Migration-Guide-V4.md +2 -1
  9. package/docs/Guides/Migration-Guide-V5.md +9 -0
  10. package/docs/Guides/Serverless.md +25 -7
  11. package/docs/Guides/Testing.md +2 -2
  12. package/docs/Reference/Decorators.md +4 -3
  13. package/docs/Reference/Encapsulation.md +2 -2
  14. package/docs/Reference/Logging.md +4 -0
  15. package/docs/Reference/Plugins.md +2 -2
  16. package/docs/Reference/Principles.md +2 -2
  17. package/docs/Reference/Reply.md +3 -2
  18. package/docs/Reference/Server.md +35 -4
  19. package/docs/Reference/TypeScript.md +2 -1
  20. package/docs/Reference/Validation-and-Serialization.md +7 -1
  21. package/examples/benchmark/webstream.js +27 -0
  22. package/fastify.d.ts +16 -21
  23. package/fastify.js +14 -9
  24. package/lib/config-validator.js +189 -223
  25. package/lib/error-handler.js +2 -5
  26. package/lib/error-status.js +14 -0
  27. package/lib/four-oh-four.js +2 -1
  28. package/lib/handle-request.js +6 -1
  29. package/lib/reply.js +53 -3
  30. package/lib/route.js +26 -12
  31. package/lib/schema-controller.js +2 -2
  32. package/lib/wrap-thenable.js +3 -0
  33. package/package.json +4 -4
  34. package/test/404s.test.js +69 -0
  35. package/test/diagnostics-channel/error-status.test.js +84 -0
  36. package/test/internals/schema-controller-perf.test.js +40 -0
  37. package/test/issue-4959.test.js +34 -9
  38. package/test/listen.1.test.js +9 -1
  39. package/test/logger/logging.test.js +38 -1
  40. package/test/router-options.test.js +169 -0
  41. package/test/server.test.js +4 -1
  42. package/test/types/fastify.test-d.ts +28 -7
  43. package/test/types/instance.test-d.ts +29 -21
  44. package/test/types/reply.test-d.ts +55 -4
  45. package/test/types/type-provider.test-d.ts +6 -6
  46. package/test/web-api.test.js +136 -0
  47. package/types/instance.d.ts +1 -1
  48. package/types/reply.d.ts +2 -2
  49. package/types/type-provider.d.ts +16 -0
  50. package/.vscode/settings.json +0 -22
  51. package/test/decorator-namespace.test._js_ +0 -30
@@ -775,6 +775,12 @@ with the following payload:
775
775
  }
776
776
  ```
777
777
 
778
+ > ⚠ Security Consideration: By default, validation error details from the schema
779
+ > are included in the response payload. If your organization requires sanitizing
780
+ > or customizing these error messages (e.g., to avoid exposing internal schema
781
+ > details), configure a custom error handler using
782
+ > [`setErrorHandler()`](./Server.md#seterrorhandler).
783
+
778
784
  To handle errors inside the route, specify the `attachValidation` option. If
779
785
  there is a validation error, the `validationError` property of the request will
780
786
  contain the `Error` object with the raw validation result as shown below:
@@ -1032,7 +1038,7 @@ const refToSharedSchemaDefinitions = {
1032
1038
 
1033
1039
  - [JSON Schema](https://json-schema.org/)
1034
1040
  - [Understanding JSON
1035
- Schema](https://spacetelescope.github.io/understanding-json-schema/)
1041
+ Schema](https://json-schema.org/understanding-json-schema/about)
1036
1042
  - [fast-json-stringify
1037
1043
  documentation](https://github.com/fastify/fast-json-stringify)
1038
1044
  - [Ajv documentation](https://github.com/epoberezkin/ajv/blob/master/README.md)
@@ -0,0 +1,27 @@
1
+ 'use strict'
2
+
3
+ const fastify = require('../../fastify')({
4
+ logger: false
5
+ })
6
+
7
+ const payload = JSON.stringify({ hello: 'world' })
8
+
9
+ fastify.get('/', function (req, reply) {
10
+ const stream = new ReadableStream({
11
+ start (controller) {
12
+ controller.enqueue(payload)
13
+ controller.close()
14
+ }
15
+ })
16
+ return new Response(stream, {
17
+ status: 200,
18
+ headers: {
19
+ 'content-type': 'application/json; charset=utf-8'
20
+ }
21
+ })
22
+ })
23
+
24
+ fastify.listen({ port: 3000 }, (err, address) => {
25
+ if (err) throw err
26
+ console.log(`Server listening on ${address}`)
27
+ })
package/fastify.d.ts CHANGED
@@ -3,10 +3,10 @@ import * as http2 from 'node:http2'
3
3
  import * as https from 'node:https'
4
4
  import { Socket } from 'node:net'
5
5
 
6
- import { Options as AjvOptions, ValidatorFactory } from '@fastify/ajv-compiler'
6
+ import { BuildCompilerFromPool, ValidatorFactory } from '@fastify/ajv-compiler'
7
7
  import { FastifyError } from '@fastify/error'
8
8
  import { Options as FJSOptions, SerializerFactory } from '@fastify/fast-json-stringify-compiler'
9
- import { ConstraintStrategy, HTTPVersion } from 'find-my-way'
9
+ import { Config as FindMyWayConfig, ConstraintStrategy, HTTPVersion } from 'find-my-way'
10
10
  import { InjectOptions, CallbackFunc as LightMyRequestCallback, Chain as LightMyRequestChain, Response as LightMyRequestResponse } from 'light-my-request'
11
11
 
12
12
  import { AddContentTypeParser, ConstructorAction, FastifyBodyParser, FastifyContentTypeParser, getDefaultJsonParser, hasContentTypeParser, ProtoAction } from './types/content-type-parser'
@@ -77,6 +77,7 @@ declare namespace fastify {
77
77
  }
78
78
 
79
79
  type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server ? HTTPVersion.V1 : HTTPVersion.V2
80
+ type FindMyWayConfigForServer<RawServer extends RawServerBase> = FindMyWayConfig<FindMyWayVersion<RawServer>>
80
81
 
81
82
  export interface ConnectionError extends Error {
82
83
  code: string,
@@ -89,20 +90,17 @@ declare namespace fastify {
89
90
 
90
91
  type TrustProxyFunction = (address: string, hop: number) => boolean
91
92
 
92
- export type FastifyRouterOptions<RawServer extends RawServerBase> = {
93
- allowUnsafeRegex?: boolean,
94
- buildPrettyMeta?: (route: { [k: string]: unknown, store: { [k: string]: unknown } }) => object,
95
- caseSensitive?: boolean,
96
- constraints?: {
97
- [name: string]: ConstraintStrategy<FindMyWayVersion<RawServer>, unknown>,
98
- },
99
- defaultRoute?: (req: FastifyRequest, res: FastifyReply) => void,
100
- ignoreDuplicateSlashes?: boolean,
101
- ignoreTrailingSlash?: boolean,
102
- maxParamLength?: number,
103
- onBadUrl?: (path: string, req: FastifyRequest, res: FastifyReply) => void,
104
- querystringParser?: (str: string) => { [key: string]: unknown },
105
- useSemicolonDelimiter?: boolean,
93
+ export type FastifyRouterOptions<RawServer extends RawServerBase> = Omit<FindMyWayConfigForServer<RawServer>, 'defaultRoute' | 'onBadUrl' | 'querystringParser'> & {
94
+ defaultRoute?: (
95
+ req: RawRequestDefaultExpression<RawServer>,
96
+ res: RawReplyDefaultExpression<RawServer>
97
+ ) => void,
98
+ onBadUrl?: (
99
+ path: string,
100
+ req: RawRequestDefaultExpression<RawServer>,
101
+ res: RawReplyDefaultExpression<RawServer>
102
+ ) => void,
103
+ querystringParser?: (str: string) => { [key: string]: unknown }
106
104
  }
107
105
 
108
106
  /**
@@ -122,7 +120,7 @@ declare namespace fastify {
122
120
  pluginTimeout?: number,
123
121
  bodyLimit?: number,
124
122
  maxParamLength?: number,
125
- disableRequestLogging?: boolean,
123
+ disableRequestLogging?: boolean | ((req: FastifyRequest) => boolean),
126
124
  exposeHeadRoutes?: boolean,
127
125
  onProtoPoisoning?: ProtoAction,
128
126
  onConstructorPoisoning?: ConstructorAction,
@@ -153,10 +151,7 @@ declare namespace fastify {
153
151
  };
154
152
  };
155
153
  return503OnClosing?: boolean,
156
- ajv?: {
157
- customOptions?: AjvOptions,
158
- plugins?: (Function | [Function, unknown])[]
159
- },
154
+ ajv?: Parameters<BuildCompilerFromPool>[1],
160
155
  frameworkErrors?: <RequestGeneric extends RequestGenericInterface = RequestGenericInterface, TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, SchemaCompiler extends FastifySchema = FastifySchema>(
161
156
  error: FastifyError,
162
157
  req: FastifyRequest<RequestGeneric, RawServer, RawRequestDefaultExpression<RawServer>, FastifySchema, TypeProvider>,
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '5.6.2'
3
+ const VERSION = '5.7.1'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('node:http')
@@ -82,7 +82,7 @@ const { FSTWRN004 } = require('./lib/warnings.js')
82
82
  const initChannel = diagnostics.channel('fastify.initialization')
83
83
 
84
84
  /**
85
- * @param {import('./fastify.js').FastifyServerOptions} options
85
+ * @param {import('./fastify.js').FastifyServerOptions} serverOptions
86
86
  */
87
87
  function fastify (serverOptions) {
88
88
  const {
@@ -94,9 +94,7 @@ function fastify (serverOptions) {
94
94
  } = processOptions(serverOptions, defaultRoute, onBadUrl)
95
95
 
96
96
  // Default router
97
- const router = buildRouting({
98
- config: options.routerOptions
99
- })
97
+ const router = buildRouting(options.routerOptions)
100
98
 
101
99
  // 404 router, used for handling encapsulated 404 handlers
102
100
  const fourOhFour = build404(options)
@@ -643,16 +641,22 @@ function fastify (serverOptions) {
643
641
  const request = new Request(id, null, req, null, childLogger, onBadUrlContext)
644
642
  const reply = new Reply(res, request, childLogger)
645
643
 
646
- if (disableRequestLogging === false) {
644
+ const resolvedDisableRequestLogging = typeof disableRequestLogging === 'function' ? disableRequestLogging(req) : disableRequestLogging
645
+ if (resolvedDisableRequestLogging === false) {
647
646
  childLogger.info({ req: request }, 'incoming request')
648
647
  }
649
648
 
650
649
  return options.frameworkErrors(new FST_ERR_BAD_URL(path), request, reply)
651
650
  }
652
- const body = `{"error":"Bad Request","code":"FST_ERR_BAD_URL","message":"'${path}' is not a valid url component","statusCode":400}`
651
+ const body = JSON.stringify({
652
+ error: 'Bad Request',
653
+ code: 'FST_ERR_BAD_URL',
654
+ message: `'${path}' is not a valid url component`,
655
+ statusCode: 400
656
+ })
653
657
  res.writeHead(400, {
654
658
  'Content-Type': 'application/json',
655
- 'Content-Length': body.length
659
+ 'Content-Length': Buffer.byteLength(body)
656
660
  })
657
661
  res.end(body)
658
662
  }
@@ -668,7 +672,8 @@ function fastify (serverOptions) {
668
672
  const request = new Request(id, null, req, null, childLogger, onBadUrlContext)
669
673
  const reply = new Reply(res, request, childLogger)
670
674
 
671
- if (disableRequestLogging === false) {
675
+ const resolvedDisableRequestLogging = typeof disableRequestLogging === 'function' ? disableRequestLogging(req) : disableRequestLogging
676
+ if (resolvedDisableRequestLogging === false) {
672
677
  childLogger.info({ req: request }, 'incoming request')
673
678
  }
674
679