diff --git a/docs/Guides/Ecosystem.md b/docs/Guides/Ecosystem.md index bb4afad83e..15dd405140 100644 --- a/docs/Guides/Ecosystem.md +++ b/docs/Guides/Ecosystem.md @@ -188,6 +188,9 @@ section. A Fastify plugin that protects against No(n)SQL injection by sanitizing data. - [`@exortek/remix-fastify`](https://github.com/ExorTek/remix-fastify) Fastify plugin for Remix. +- [`@glidemq/fastify`](https://github.com/avifenesh/glidemq-fastify) + Queue management plugin for glide-mq with REST API endpoints, SSE events, + and in-memory testing mode. Powered by Valkey/Redis Streams. - [`@gquittet/graceful-server`](https://github.com/gquittet/graceful-server) Tiny (~5k), Fast, KISS, and dependency-free Node.js library to make your Fastify API graceful. @@ -207,6 +210,9 @@ section. A Fastify plugin that enforces naming pattern for routes path. - [`@joggr/fastify-prisma`](https://github.com/joggrdocs/fastify-prisma) A plugin for accessing an instantiated PrismaClient on your server. +- [`@matths/fastify-svelte-view`](https://github.com/matths/fastify-svelte-view) + A Fastify plugin for rendering Svelte components with support for SSR + (Server-Side Rendering), CSR (Client-Side Rendering), and SSR with hydration. - [`@mgcrea/fastify-graceful-exit`](https://github.com/mgcrea/fastify-graceful-exit) A plugin to close the server gracefully - [`@mgcrea/fastify-request-logger`](https://github.com/mgcrea/fastify-request-logger) @@ -225,6 +231,8 @@ section. Beautiful OpenAPI/Swagger API references for Fastify - [`@trubavuong/fastify-seaweedfs`](https://github.com/trubavuong/fastify-seaweedfs) SeaweedFS for Fastify +- [`@yeliex/fastify-problem-details`](https://github.com/yeliex/fastify-problem-details) + RFC 9457 Problem Details implementation for Fastify, with typed HTTP errors. - [`apitally`](https://github.com/apitally/apitally-js) Fastify plugin to integrate with [Apitally](https://apitally.io/fastify), an API analytics, logging and monitoring tool. @@ -366,6 +374,8 @@ section. Fastify feature flags plugin with multiple providers support (e.g. env, [config](https://lorenwest.github.io/node-config/), [unleash](https://github.com/Unleash/unleash)). +- [`fastify-file-router`](https://github.com/bhouston/fastify-file-router) + A typesafe TanStack Start / Next.JS-style router with JSON + Zod schema support. - [`fastify-file-routes`](https://github.com/spa5k/fastify-file-routes) Get Next.js based file system routing into fastify. - [`fastify-formidable`](https://github.com/climba03003/fastify-formidable) diff --git a/docs/Guides/Migration-Guide-V4.md b/docs/Guides/Migration-Guide-V4.md index 3dd4f23a91..7fc50a74ff 100644 --- a/docs/Guides/Migration-Guide-V4.md +++ b/docs/Guides/Migration-Guide-V4.md @@ -14,24 +14,19 @@ To help with the upgrade, we’ve worked with the team at publish codemods that will automatically update your code to many of the new APIs and patterns in Fastify v4. -Run the following -[migration recipe](https://go.codemod.com/fastify-4-migration-recipe) to -automatically update your code to Fastify v4: -``` +```bash npx codemod@latest fastify/4/migration-recipe ``` +This applies the following codemods: -This will run the following codemods: - -- [`fastify/4/remove-app-use`](https://go.codemod.com/fastify-4-remove-app-use) -- [`fastify/4/reply-raw-access`](https://go.codemod.com/fastify-4-reply-raw-access) -- [`fastify/4/wrap-routes-plugin`](https://go.codemod.com/fastify-4-wrap-routes-plugin) -- [`fastify/4/await-register-calls`](https://go.codemod.com/fastify-4-await-register-calls) +- fastify/4/remove-app-use +- fastify/4/reply-raw-access +- fastify/4/wrap-routes-plugin +- fastify/4/await-register-calls -Each of these codemods automates the changes listed in the v4 migration guide. -For a complete list of available Fastify codemods and further details, -see [Codemod Registry](https://go.codemod.com/fastify). +For information on the migration recipe, see +https://app.codemod.com/registry/fastify/4/migration-recipe. ## Breaking Changes diff --git a/docs/Reference/ContentTypeParser.md b/docs/Reference/ContentTypeParser.md index c2b05e59e4..8f92873da4 100644 --- a/docs/Reference/ContentTypeParser.md +++ b/docs/Reference/ContentTypeParser.md @@ -17,6 +17,13 @@ declared in a plugin, it is available only in that scope and its children. Fastify automatically adds the parsed request payload to the [Fastify request](./Request.md) object, accessible via `request.body`. +> **Important:** When using a body schema with the +> [`content`](./Validation-and-Serialization.md#body-content-type-validation) +> property to validate per content type, only content types listed in the schema +> will be validated. If you add a custom content type parser but do not include +> its content type in the body schema's `content` property, the incoming data +> will be parsed but **not validated**. + Note that for `GET` and `HEAD` requests, the payload is never parsed. For `OPTIONS` and `DELETE` requests, the payload is parsed only if a valid `content-type` header is provided. Unlike `POST`, `PUT`, and `PATCH`, the diff --git a/docs/Reference/Server.md b/docs/Reference/Server.md index 3a3426f384..3b859f5036 100644 --- a/docs/Reference/Server.md +++ b/docs/Reference/Server.md @@ -1784,7 +1784,10 @@ call is encapsulated by prefix, so different plugins can set different not found handlers if a different [`prefix` option](./Plugins.md#route-prefixing-option) is passed to `fastify.register()`. The handler is treated as a regular route handler so requests will go through the full [Fastify -lifecycle](./Lifecycle.md#lifecycle). *async-await* is supported as well. +lifecycle](./Lifecycle.md#lifecycle) for unexisting URLs. +*async-await* is supported as well. +Badly formatted URLs are sent to the [`onBadUrl`](#onbadurl) +handler instead. You can also register [`preValidation`](./Hooks.md#route-hooks) and [`preHandler`](./Hooks.md#route-hooks) hooks for the 404 handler. diff --git a/docs/Reference/Validation-and-Serialization.md b/docs/Reference/Validation-and-Serialization.md index 7d3504bc28..204492157a 100644 --- a/docs/Reference/Validation-and-Serialization.md +++ b/docs/Reference/Validation-and-Serialization.md @@ -5,7 +5,11 @@ Fastify uses a schema-based approach. We recommend using [JSON Schema](https://json-schema.org/) to validate routes and serialize outputs. Fastify compiles the schema into a highly performant function. -Validation is only attempted if the content type is `application/json`. +Validation is only attempted if the content type is `application/json`, +unless the body schema uses the [`content`](#body-content-type-validation) +property to specify validation per content type. When the body schema defines +a `content` field, it must enumerate all possible content types the +application expects to handle with the associated handler. All examples use the [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7) @@ -228,6 +232,9 @@ const schema = { fastify.post('/the/url', { schema }, handler) ``` +#### Body Content-Type Validation + + For `body` schema, it is further possible to differentiate the schema per content type by nesting the schemas inside `content` property. The schema validation will be applied based on the `Content-Type` header in the request. @@ -250,6 +257,36 @@ fastify.post('/the/url', { }, handler) ``` +> **Important:** When using [custom content type +> parsers](./ContentTypeParser.md), the parsed body will **only** be validated +> if the request's content type is listed in the `content` object above. If +> a parser for a content type (e.g., `application/yaml`) is defined, +> but it is not not included in the body schema's `content` property, +> the incoming data will be parsed but **not validated**. +> +> ```js +> // Add a custom parser for YAML +> fastify.addContentTypeParser('application/yaml', { parseAs: 'string' }, (req, body, done) => { +> done(null, YAML.parse(body)) +> }) +> +> fastify.post('/the/url', { +> schema: { +> body: { +> content: { +> 'application/json': { +> schema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] } +> }, +> // Without this entry, application/yaml requests will NOT be validated +> 'application/yaml': { +> schema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] } +> } +> } +> } +> } +> }, handler) +> ``` + Note that Ajv will try to [coerce](https://ajv.js.org/coercion.html) values to the types specified in the schema `type` keywords, both to pass validation and to use the correctly typed data afterwards. diff --git a/fastify.js b/fastify.js index fdde55f835..343ce5de5c 100644 --- a/fastify.js +++ b/fastify.js @@ -1,6 +1,6 @@ 'use strict' -const VERSION = '5.8.1' +const VERSION = '5.8.2' const Avvio = require('avvio') const http = require('node:http') diff --git a/lib/content-type.js b/lib/content-type.js index db548de2ef..1e3e51562d 100644 --- a/lib/content-type.js +++ b/lib/content-type.js @@ -2,12 +2,14 @@ /** * keyValuePairsReg is used to split the parameters list into associated - * key value pairings. + * key value pairings. The leading `(?:^|;)\s*` anchor ensures the regex + * only attempts matches at parameter boundaries, preventing quadratic + * backtracking on malformed input. * * @see https://httpwg.org/specs/rfc9110.html#parameter * @type {RegExp} */ -const keyValuePairsReg = /([\w!#$%&'*+.^`|~-]+)=([^;]*)/gm +const keyValuePairsReg = /(?:^|;)\s*([\w!#$%&'*+.^`|~-]+)=([^;]*)/gm /** * typeNameReg is used to validate that the first part of the media-type diff --git a/package.json b/package.json index ae313b4f5e..d0cae6c025 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fastify", - "version": "5.8.1", + "version": "5.8.2", "description": "Fast and low overhead web framework, for Node.js", "main": "fastify.js", "type": "commonjs", @@ -177,7 +177,7 @@ "ajv-i18n": "^4.2.0", "ajv-merge-patch": "^5.0.1", "autocannon": "^8.0.0", - "borp": "^1.0.0", + "borp": "^0.21.0", "branch-comparer": "^1.1.0", "concurrently": "^9.1.2", "cross-env": "^10.0.0",