fastify 5.10.0 → 5.11.0
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.
- package/SPONSORS.md +1 -0
- package/docs/Guides/Ecosystem.md +2 -2
- package/docs/Guides/Getting-Started.md +8 -8
- package/docs/Reference/Errors.md +4 -0
- package/docs/Reference/Reply.md +2 -2
- package/docs/Reference/Request.md +11 -11
- package/docs/Reference/Server.md +16 -15
- package/docs/Reference/TypeScript.md +5 -7
- package/docs/Reference/Warnings.md +1 -0
- package/eslint.config.js +1 -1
- package/fastify.d.ts +55 -13
- package/fastify.js +7 -2
- package/lib/content-type.js +36 -18
- package/lib/errors.js +10 -0
- package/lib/handle-request.js +35 -7
- package/lib/hooks.js +5 -1
- package/lib/route.js +1 -1
- package/lib/schemas.js +3 -3
- package/lib/validation.js +1 -1
- package/package.json +2 -2
- package/test/content-type.test.js +31 -4
- package/test/find-route.test.js +35 -0
- package/test/fix-6411.test.js +65 -0
- package/test/internals/all.test.js +2 -1
- package/test/internals/errors.test.js +21 -1
- package/test/internals/reply.test.js +22 -0
- package/test/reply-error.test.js +35 -0
- package/test/rfc-10008.test.js +147 -0
- package/test/route-shorthand.test.js +14 -4
- package/test/schema-serialization.test.js +33 -0
- package/test/types/errors.tst.ts +2 -0
- package/test/types/route.tst.ts +3 -3
- package/types/content-type-parser.d.ts +26 -6
- package/types/errors.d.ts +2 -0
- package/types/hooks.d.ts +137 -76
- package/types/instance.d.ts +150 -47
- package/types/logger.d.ts +36 -3
- package/types/plugin.d.ts +7 -3
- package/types/register.d.ts +53 -10
- package/types/reply.d.ts +62 -14
- package/types/route.d.ts +68 -34
- package/types/type-provider.d.ts +29 -8
- package/types/utils.d.ts +2 -2
package/SPONSORS.md
CHANGED
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -208,8 +208,6 @@ section.
|
|
|
208
208
|
Type-safe dependency injection support for Fastify, powered by [InferDI](https://github.com/inferdi/inferdi).
|
|
209
209
|
- [`@jerome1337/fastify-enforce-routes-pattern`](https://github.com/Jerome1337/fastify-enforce-routes-pattern)
|
|
210
210
|
A Fastify plugin that enforces naming pattern for routes path.
|
|
211
|
-
- [`@joggr/fastify-prisma`](https://github.com/joggrdocs/fastify-prisma)
|
|
212
|
-
A plugin for accessing an instantiated PrismaClient on your server.
|
|
213
211
|
- [`@matths/fastify-svelte-view`](https://github.com/matths/fastify-svelte-view)
|
|
214
212
|
A Fastify plugin for rendering Svelte components with support for SSR
|
|
215
213
|
(Server-Side Rendering), CSR (Client-Side Rendering), and SSR with hydration.
|
|
@@ -242,6 +240,8 @@ section.
|
|
|
242
240
|
SeaweedFS for Fastify
|
|
243
241
|
- [`@yeliex/fastify-problem-details`](https://github.com/yeliex/fastify-problem-details)
|
|
244
242
|
RFC 9457 Problem Details implementation for Fastify, with typed HTTP errors.
|
|
243
|
+
- [`@zrosenbauer/fastify-prisma`](https://github.com/zrosenbauer/fastify-prisma)
|
|
244
|
+
A plugin for accessing an instantiated PrismaClient on your server.
|
|
245
245
|
- [`apitally`](https://github.com/apitally/apitally-js) Fastify plugin to
|
|
246
246
|
integrate with [Apitally](https://apitally.io/fastify), an API analytics,
|
|
247
247
|
logging and monitoring tool.
|
|
@@ -146,7 +146,7 @@ declaration](../Reference/Routes.md) docs).
|
|
|
146
146
|
```js
|
|
147
147
|
// ESM
|
|
148
148
|
import Fastify from 'fastify'
|
|
149
|
-
import
|
|
149
|
+
import routes from './our-first-routes.js'
|
|
150
150
|
/**
|
|
151
151
|
* @type {import('fastify').FastifyInstance} Instance of Fastify
|
|
152
152
|
*/
|
|
@@ -154,7 +154,7 @@ const fastify = Fastify({
|
|
|
154
154
|
logger: true
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
-
fastify.register(
|
|
157
|
+
fastify.register(routes)
|
|
158
158
|
|
|
159
159
|
fastify.listen({ port: 3000 }, function (err, address) {
|
|
160
160
|
if (err) {
|
|
@@ -174,7 +174,7 @@ const fastify = require('fastify')({
|
|
|
174
174
|
logger: true
|
|
175
175
|
})
|
|
176
176
|
|
|
177
|
-
fastify.register(require('./our-first-
|
|
177
|
+
fastify.register(require('./our-first-routes'))
|
|
178
178
|
|
|
179
179
|
fastify.listen({ port: 3000 }, function (err, address) {
|
|
180
180
|
if (err) {
|
|
@@ -187,7 +187,7 @@ fastify.listen({ port: 3000 }, function (err, address) {
|
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
```js
|
|
190
|
-
// our-first-
|
|
190
|
+
// our-first-routes.js
|
|
191
191
|
|
|
192
192
|
/**
|
|
193
193
|
* Encapsulates the routes
|
|
@@ -236,7 +236,7 @@ npm i fastify-plugin @fastify/mongodb
|
|
|
236
236
|
// ESM
|
|
237
237
|
import Fastify from 'fastify'
|
|
238
238
|
import dbConnector from './our-db-connector.js'
|
|
239
|
-
import
|
|
239
|
+
import routes from './our-first-routes.js'
|
|
240
240
|
|
|
241
241
|
/**
|
|
242
242
|
* @type {import('fastify').FastifyInstance} Instance of Fastify
|
|
@@ -245,7 +245,7 @@ const fastify = Fastify({
|
|
|
245
245
|
logger: true
|
|
246
246
|
})
|
|
247
247
|
fastify.register(dbConnector)
|
|
248
|
-
fastify.register(
|
|
248
|
+
fastify.register(routes)
|
|
249
249
|
|
|
250
250
|
fastify.listen({ port: 3000 }, function (err, address) {
|
|
251
251
|
if (err) {
|
|
@@ -266,7 +266,7 @@ const fastify = require('fastify')({
|
|
|
266
266
|
})
|
|
267
267
|
|
|
268
268
|
fastify.register(require('./our-db-connector'))
|
|
269
|
-
fastify.register(require('./our-first-
|
|
269
|
+
fastify.register(require('./our-first-routes'))
|
|
270
270
|
|
|
271
271
|
fastify.listen({ port: 3000 }, function (err, address) {
|
|
272
272
|
if (err) {
|
|
@@ -325,7 +325,7 @@ module.exports = fastifyPlugin(dbConnector)
|
|
|
325
325
|
|
|
326
326
|
```
|
|
327
327
|
|
|
328
|
-
**our-first-
|
|
328
|
+
**our-first-routes.js**
|
|
329
329
|
```js
|
|
330
330
|
/**
|
|
331
331
|
* A plugin that provide encapsulated routes
|
package/docs/Reference/Errors.md
CHANGED
|
@@ -91,6 +91,8 @@
|
|
|
91
91
|
|
|
92
92
|
- [FST_ERR_ROUTE_HANDLER_TIMEOUT_OPTION_NOT_INT](#fst_err_route_handler_timeout_option_not_int)
|
|
93
93
|
- [FST_ERR_ROUTE_REWRITE_NOT_STR](#fst_err_route_rewrite_not_str)
|
|
94
|
+
- [FST_ERR_ROUTE_MISSING_CONTENT_TYPE](#fst_err_route_missing_content_type)
|
|
95
|
+
- [FST_ERR_ROUTE_MISSING_CONTENT](#fst_err_route_missing_content)
|
|
94
96
|
- [FST_ERR_REOPENED_CLOSE_SERVER](#fst_err_reopened_close_server)
|
|
95
97
|
- [FST_ERR_REOPENED_SERVER](#fst_err_reopened_server)
|
|
96
98
|
- [FST_ERR_PLUGIN_VERSION_MISMATCH](#fst_err_plugin_version_mismatch)
|
|
@@ -369,6 +371,8 @@ Below is a table with all the error codes used by Fastify.
|
|
|
369
371
|
| <a id="fst_err_handler_timeout">FST_ERR_HANDLER_TIMEOUT</a> | Request timed out. | Increase the `handlerTimeout` option or optimize the handler. | - |
|
|
370
372
|
| <a id="fst_err_route_handler_timeout_option_not_int">FST_ERR_ROUTE_HANDLER_TIMEOUT_OPTION_NOT_INT</a> | `handlerTimeout` option must be a positive integer. | Use a positive integer for the `handlerTimeout` option. | - |
|
|
371
373
|
| <a id="fst_err_route_rewrite_not_str">FST_ERR_ROUTE_REWRITE_NOT_STR</a> | `rewriteUrl` needs to be of type `string`. | Use a string for the `rewriteUrl`. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
|
374
|
+
| <a id="fst_err_route_missing_content_type">FST_ERR_ROUTE_MISSING_CONTENT_TYPE</a> | `Content-Type` header is required for the request. | Send request with `Content-Type` header. | [#6832](https://github.com/fastify/fastify/pull/6832) |
|
|
375
|
+
| <a id="fst_err_route_missing_content">FST_ERR_ROUTE_MISSING_CONTENT</a> | Body is required for the request. | Send request with payload. | [#6832](https://github.com/fastify/fastify/pull/6832) |
|
|
372
376
|
| <a id="fst_err_reopened_close_server">FST_ERR_REOPENED_CLOSE_SERVER</a> | Fastify has already been closed and cannot be reopened. | - | [#2415](https://github.com/fastify/fastify/pull/2415) |
|
|
373
377
|
| <a id="fst_err_reopened_server">FST_ERR_REOPENED_SERVER</a> | Fastify is already listening. | - | [#2415](https://github.com/fastify/fastify/pull/2415) |
|
|
374
378
|
| <a id="fst_err_plugin_version_mismatch">FST_ERR_PLUGIN_VERSION_MISMATCH</a> | Installed Fastify plugin mismatched expected version. | Use a compatible version of the plugin. | [#2549](https://github.com/fastify/fastify/pull/2549) |
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -271,7 +271,7 @@ as soon as possible.
|
|
|
271
271
|
> in the error, you can turn on `debug` level logging.
|
|
272
272
|
|
|
273
273
|
```js
|
|
274
|
-
reply.trailer('server-timing', function() {
|
|
274
|
+
reply.trailer('server-timing', async function () {
|
|
275
275
|
return 'db;dur=53, app;dur=47.2'
|
|
276
276
|
})
|
|
277
277
|
|
|
@@ -304,7 +304,7 @@ Returns a boolean indicating if the specified trailer has been set.
|
|
|
304
304
|
|
|
305
305
|
Remove the value of a previously set trailer.
|
|
306
306
|
```js
|
|
307
|
-
reply.trailer('server-timing', function() {
|
|
307
|
+
reply.trailer('server-timing', async function () {
|
|
308
308
|
return 'db;dur=53, app;dur=47.2'
|
|
309
309
|
})
|
|
310
310
|
reply.removeTrailer('server-timing')
|
|
@@ -34,14 +34,14 @@ Request is a core Fastify object containing the following fields:
|
|
|
34
34
|
value comes from `socket.encrypted` (or `X-Forwarded-Proto` when
|
|
35
35
|
[`trustProxy`](./Server.md#factory-trust-proxy) is enabled).
|
|
36
36
|
|
|
37
|
-
> ⚠️ Security:
|
|
38
|
-
> `request.ip`, `request.ips`, `request.host`, `request.hostname`,
|
|
39
|
-
> `request.port`, and `request.protocol` come from request metadata
|
|
40
|
-
> (socket and/or forwarding headers) and should be treated as untrusted input.
|
|
41
|
-
> Fastify does not perform security validation for business logic.
|
|
42
|
-
> If these values are used in security-sensitive decisions, they must
|
|
43
|
-
> be validated explicitly (for example: trusted proxy configuration,
|
|
44
|
-
> allow-lists, strict parsing, and normalization).
|
|
37
|
+
> ⚠️ Security:
|
|
38
|
+
> `request.ip`, `request.ips`, `request.host`, `request.hostname`,
|
|
39
|
+
> `request.port`, and `request.protocol` come from request metadata
|
|
40
|
+
> (socket and/or forwarding headers) and should be treated as untrusted input.
|
|
41
|
+
> Fastify does not perform security validation for business logic.
|
|
42
|
+
> If these values are used in security-sensitive decisions, they must
|
|
43
|
+
> be validated explicitly (for example: trusted proxy configuration,
|
|
44
|
+
> allow-lists, strict parsing, and normalization).
|
|
45
45
|
|
|
46
46
|
- `method` - The method of the incoming request.
|
|
47
47
|
- `url` - The URL of the incoming request.
|
|
@@ -87,9 +87,9 @@ Request is a core Fastify object containing the following fields:
|
|
|
87
87
|
default (or customized) `ValidationCompiler`. The optional `httpPart` is
|
|
88
88
|
forwarded to the `ValidationCompiler` if provided, defaults to `null`.
|
|
89
89
|
- [.validateInput(data, schema | httpPart, [httpPart])](#validate) -
|
|
90
|
-
Validates the input using the specified schema and returns
|
|
91
|
-
|
|
92
|
-
that HTTP
|
|
90
|
+
Validates the input using the specified schema or HTTP part and returns
|
|
91
|
+
`true` if the input is valid, `false` otherwise. If `httpPart` is provided,
|
|
92
|
+
the function uses the validator for that HTTP part. Defaults to `null`.
|
|
93
93
|
|
|
94
94
|
### Headers
|
|
95
95
|
|
package/docs/Reference/Server.md
CHANGED
|
@@ -390,8 +390,8 @@ Pino interface by having the following methods: `info`, `error`, `debug`,
|
|
|
390
390
|
### `disableRequestLogging`
|
|
391
391
|
<a id="factory-disable-request-logging"></a>
|
|
392
392
|
|
|
393
|
-
> **Deprecated:** Use the [`logController`](#log-controller)
|
|
394
|
-
> `disableRequestLogging` or `isLogDisabled` override instead.
|
|
393
|
+
> **Deprecated:** Use the [`logController`](#factory-log-controller)
|
|
394
|
+
> option with `disableRequestLogging` or `isLogDisabled` override instead.
|
|
395
395
|
> This top-level option will be removed in `fastify@6`.
|
|
396
396
|
|
|
397
397
|
+ Default: `false`
|
|
@@ -407,6 +407,8 @@ and returns a boolean. This allows for conditional request logging based on the
|
|
|
407
407
|
request properties (e.g., URL, headers, decorations).
|
|
408
408
|
|
|
409
409
|
```js
|
|
410
|
+
const { LogController } = require('fastify')
|
|
411
|
+
|
|
410
412
|
// Deprecated
|
|
411
413
|
const fastify = require('fastify')({
|
|
412
414
|
logger: true,
|
|
@@ -418,11 +420,11 @@ const fastify = require('fastify')({
|
|
|
418
420
|
// Recommended: use logController instead
|
|
419
421
|
const fastify = require('fastify')({
|
|
420
422
|
logger: true,
|
|
421
|
-
logController: {
|
|
423
|
+
logController: new LogController({
|
|
422
424
|
disableRequestLogging: (request) => {
|
|
423
425
|
return request.url === '/health' || request.url === '/ready'
|
|
424
426
|
}
|
|
425
|
-
}
|
|
427
|
+
})
|
|
426
428
|
})
|
|
427
429
|
```
|
|
428
430
|
|
|
@@ -567,7 +569,7 @@ enhance the server instance inside the `serverFactory` function before the
|
|
|
567
569
|
### `requestIdHeader`
|
|
568
570
|
<a id="factory-request-id-header"></a>
|
|
569
571
|
|
|
570
|
-
+ Default: `
|
|
572
|
+
+ Default: `false`
|
|
571
573
|
|
|
572
574
|
The header name used to set the request-id. See [the
|
|
573
575
|
request-id](./Logging.md#logging-request-id) section.
|
|
@@ -579,8 +581,6 @@ By default `requestIdHeader` is set to `false` and will immediately use [genReqI
|
|
|
579
581
|
Setting `requestIdHeader` to an empty String (`""`) will set the
|
|
580
582
|
requestIdHeader to `false`.
|
|
581
583
|
|
|
582
|
-
+ Default: `false`
|
|
583
|
-
|
|
584
584
|
```js
|
|
585
585
|
const fastify = require('fastify')({
|
|
586
586
|
requestIdHeader: 'x-custom-id', // -> use 'X-Custom-Id' header if available
|
|
@@ -596,8 +596,9 @@ const fastify = require('fastify')({
|
|
|
596
596
|
### `requestIdLogLabel`
|
|
597
597
|
<a id="factory-request-id-log-label"></a>
|
|
598
598
|
|
|
599
|
-
> **Deprecated:** Use the [`logController`](#log-controller)
|
|
600
|
-
> `requestIdLogLabel` instead. This top-level option will be
|
|
599
|
+
> **Deprecated:** Use the [`logController`](#factory-log-controller)
|
|
600
|
+
> option with `requestIdLogLabel` instead. This top-level option will be
|
|
601
|
+
> removed in `fastify@6`.
|
|
601
602
|
|
|
602
603
|
+ Default: `'reqId'`
|
|
603
604
|
|
|
@@ -659,11 +660,11 @@ For more examples, refer to the
|
|
|
659
660
|
You may access the `ip`, `ips`, `host` and `protocol` values on the
|
|
660
661
|
[`request`](./Request.md) object.
|
|
661
662
|
|
|
662
|
-
> ⚠️ Security:
|
|
663
|
-
> These values are derived from socket/forwarding metadata and must be treated
|
|
664
|
-
> as untrusted input unless your proxy chain is explicitly trusted and
|
|
665
|
-
> validated. Do not use them directly for authorization or other
|
|
666
|
-
> security-sensitive decisions without explicit validation.
|
|
663
|
+
> ⚠️ Security:
|
|
664
|
+
> These values are derived from socket/forwarding metadata and must be treated
|
|
665
|
+
> as untrusted input unless your proxy chain is explicitly trusted and
|
|
666
|
+
> validated. Do not use them directly for authorization or other
|
|
667
|
+
> security-sensitive decisions without explicit validation.
|
|
667
668
|
|
|
668
669
|
```js
|
|
669
670
|
fastify.get('/', (request, reply) => {
|
|
@@ -1702,7 +1703,7 @@ Fake HTTP injection (for testing purposes)
|
|
|
1702
1703
|
<a id="addHttpMethod"></a>
|
|
1703
1704
|
|
|
1704
1705
|
Fastify supports the `GET`, `HEAD`, `TRACE`, `DELETE`, `OPTIONS`,
|
|
1705
|
-
`PATCH`, `PUT` and `
|
|
1706
|
+
`PATCH`, `PUT`, `POST` and `QUERY` HTTP methods by default.
|
|
1706
1707
|
The `addHttpMethod` method allows to add any non standard HTTP
|
|
1707
1708
|
methods to the server that are [supported by Node.js](https://nodejs.org/api/http.html#httpmethods).
|
|
1708
1709
|
|
|
@@ -15,7 +15,7 @@ fill in the gaps. Just make sure to read our
|
|
|
15
15
|
[`CONTRIBUTING.md`](https://github.com/fastify/fastify/blob/main/CONTRIBUTING.md)
|
|
16
16
|
file before getting started to make sure things go smoothly!
|
|
17
17
|
|
|
18
|
-
> The documentation in this section covers Fastify
|
|
18
|
+
> The documentation in this section covers Fastify typings
|
|
19
19
|
|
|
20
20
|
> Plugins may or may not include typings. See [Plugins](#plugins) for more
|
|
21
21
|
> information. We encourage users to send pull requests to improve typings
|
|
@@ -90,7 +90,7 @@ in a blank http Fastify server.
|
|
|
90
90
|
🏓
|
|
91
91
|
|
|
92
92
|
🎉 You now have a working Typescript Fastify server! This example demonstrates
|
|
93
|
-
the simplicity of the
|
|
93
|
+
the simplicity of the type system. By default, the type system
|
|
94
94
|
assumes you are using an `http` server. The later examples will demonstrate how
|
|
95
95
|
to create more complex servers such as `https` and `http2`, how to specify route
|
|
96
96
|
schemas, and more!
|
|
@@ -545,9 +545,9 @@ Fastify Plugin in a TypeScript Project.
|
|
|
545
545
|
}
|
|
546
546
|
|
|
547
547
|
// export plugin using fastify-plugin
|
|
548
|
-
export default fp(myPluginCallback
|
|
548
|
+
export default fp(myPluginCallback)
|
|
549
549
|
// or
|
|
550
|
-
// export default fp(myPluginAsync
|
|
550
|
+
// export default fp(myPluginAsync)
|
|
551
551
|
```
|
|
552
552
|
6. Run `npm run build` to compile the plugin code and produce both a JavaScript
|
|
553
553
|
source file and a type definition file.
|
|
@@ -595,7 +595,6 @@ your plugin.
|
|
|
595
595
|
}
|
|
596
596
|
|
|
597
597
|
module.exports = fp(myPlugin, {
|
|
598
|
-
fastify: '5.x',
|
|
599
598
|
name: 'my-plugin' // this is used by fastify-plugin to derive the property name
|
|
600
599
|
})
|
|
601
600
|
```
|
|
@@ -843,8 +842,7 @@ module.exports = async function (fastify, { optionA, optionB }) {
|
|
|
843
842
|
|
|
844
843
|
## API Type System Documentation
|
|
845
844
|
|
|
846
|
-
This section is a detailed account of all the types available to you in Fastify
|
|
847
|
-
version 3.x
|
|
845
|
+
This section is a detailed account of all the types available to you in Fastify.
|
|
848
846
|
|
|
849
847
|
All `http`, `https`, and `http2` types are inferred from `@types/node`
|
|
850
848
|
|
|
@@ -33,6 +33,7 @@ one of the following methods:
|
|
|
33
33
|
- Set the `NODE_NO_WARNINGS` environment variable to `1`
|
|
34
34
|
- Pass the `--no-warnings` flag to the node process
|
|
35
35
|
- Set `no-warnings` in the `NODE_OPTIONS` environment variable
|
|
36
|
+
- Pass `--disable-warning=FSTWRN004` to disable a specific warning
|
|
36
37
|
|
|
37
38
|
For more information on disabling warnings, see [Node's documentation](https://nodejs.org/api/cli.html).
|
|
38
39
|
|
package/eslint.config.js
CHANGED
package/fastify.d.ts
CHANGED
|
@@ -78,7 +78,9 @@ declare namespace fastify {
|
|
|
78
78
|
http?: http.ServerOptions | null
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server
|
|
81
|
+
type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server
|
|
82
|
+
? HTTPVersion.V1
|
|
83
|
+
: HTTPVersion.V2
|
|
82
84
|
type FindMyWayConfigForServer<RawServer extends RawServerBase> = FindMyWayConfig<FindMyWayVersion<RawServer>>
|
|
83
85
|
|
|
84
86
|
export interface ConnectionError extends Error {
|
|
@@ -163,15 +165,39 @@ declare namespace fastify {
|
|
|
163
165
|
};
|
|
164
166
|
return503OnClosing?: boolean,
|
|
165
167
|
ajv?: Parameters<BuildCompilerFromPool>[1],
|
|
166
|
-
frameworkErrors?: <
|
|
168
|
+
frameworkErrors?: <
|
|
169
|
+
RequestGeneric extends RequestGenericInterface = RequestGenericInterface,
|
|
170
|
+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
|
|
171
|
+
SchemaCompiler extends FastifySchema = FastifySchema
|
|
172
|
+
>(
|
|
167
173
|
error: FastifyError,
|
|
168
|
-
req: FastifyRequest<
|
|
169
|
-
|
|
174
|
+
req: FastifyRequest<
|
|
175
|
+
RequestGeneric,
|
|
176
|
+
RawServer,
|
|
177
|
+
RawRequestDefaultExpression<RawServer>,
|
|
178
|
+
FastifySchema,
|
|
179
|
+
TypeProvider
|
|
180
|
+
>,
|
|
181
|
+
res: FastifyReply<
|
|
182
|
+
RequestGeneric,
|
|
183
|
+
RawServer,
|
|
184
|
+
RawRequestDefaultExpression<RawServer>,
|
|
185
|
+
RawReplyDefaultExpression<RawServer>,
|
|
186
|
+
FastifyContextConfig,
|
|
187
|
+
SchemaCompiler,
|
|
188
|
+
TypeProvider
|
|
189
|
+
>
|
|
170
190
|
) => void,
|
|
171
191
|
rewriteUrl?: (
|
|
172
192
|
// The RawRequestDefaultExpression, RawReplyDefaultExpression, and FastifyTypeProviderDefault parameters
|
|
173
193
|
// should be narrowed further but those generic parameters are not passed to this FastifyServerOptions type
|
|
174
|
-
this: FastifyInstance<
|
|
194
|
+
this: FastifyInstance<
|
|
195
|
+
RawServer,
|
|
196
|
+
RawRequestDefaultExpression<RawServer>,
|
|
197
|
+
RawReplyDefaultExpression<RawServer>,
|
|
198
|
+
Logger,
|
|
199
|
+
FastifyTypeProviderDefault
|
|
200
|
+
>,
|
|
175
201
|
req: RawRequestDefaultExpression<RawServer>
|
|
176
202
|
) => string,
|
|
177
203
|
schemaErrorFormatter?: SchemaErrorFormatter,
|
|
@@ -198,13 +224,25 @@ declare namespace fastify {
|
|
|
198
224
|
FastifyListenOptions, FastifyInstance, PrintRoutesOptions, // './types/instance'
|
|
199
225
|
FastifyLoggerOptions, FastifyBaseLogger, FastifyLoggerInstance, FastifyLogFn, LogLevel, // './types/logger'
|
|
200
226
|
FastifyRequestContext, FastifyContextConfig, FastifyReplyContext, // './types/context'
|
|
201
|
-
RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions,
|
|
227
|
+
RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions,
|
|
228
|
+
RouteShorthandOptionsWithHandler, RouteGenericInterface, // './types/route'
|
|
202
229
|
FastifyRegister, FastifyRegisterOptions, RegisterOptions, // './types/register'
|
|
203
|
-
FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser,
|
|
230
|
+
FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser,
|
|
231
|
+
ProtoAction, ConstructorAction, // './types/content-type-parser'
|
|
204
232
|
FastifyError, // '@fastify/error'
|
|
205
233
|
FastifySchema, FastifySchemaValidationError, FastifySchemaCompiler, FastifySerializerCompiler, // './types/schema'
|
|
206
|
-
HTTPMethods, RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault,
|
|
207
|
-
|
|
234
|
+
HTTPMethods, RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault,
|
|
235
|
+
ContextConfigDefault, RequestBodyDefault, RequestQuerystringDefault, RequestParamsDefault, RequestHeadersDefault,
|
|
236
|
+
// './types/utils'
|
|
237
|
+
DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler,
|
|
238
|
+
onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler,
|
|
239
|
+
onListenAsyncHookHandler, onListenHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler,
|
|
240
|
+
onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler,
|
|
241
|
+
onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler,
|
|
242
|
+
preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler,
|
|
243
|
+
preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler,
|
|
244
|
+
preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler, preCloseAsyncHookHandler,
|
|
245
|
+
preCloseHookHandler, // './types/hooks'
|
|
208
246
|
FastifyServerFactory, FastifyServerFactoryHandler, // './types/serverFactory'
|
|
209
247
|
FastifyTypeProvider, FastifyTypeProviderDefault, SafePromiseLike, // './types/type-provider'
|
|
210
248
|
FastifyErrorCodes // './types/errors'
|
|
@@ -232,7 +270,8 @@ declare function fastify<
|
|
|
232
270
|
Reply extends RawReplyDefaultExpression<Server> = RawReplyDefaultExpression<Server>,
|
|
233
271
|
Logger extends FastifyBaseLogger = FastifyBaseLogger,
|
|
234
272
|
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
235
|
-
> (opts: fastify.FastifyHttp2SecureOptions<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
273
|
+
> (opts: fastify.FastifyHttp2SecureOptions<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
274
|
+
TypeProvider> & SafePromiseLike<FastifyInstance<Server, Request, Reply, Logger, TypeProvider>>
|
|
236
275
|
|
|
237
276
|
declare function fastify<
|
|
238
277
|
Server extends http2.Http2Server,
|
|
@@ -240,7 +279,8 @@ declare function fastify<
|
|
|
240
279
|
Reply extends RawReplyDefaultExpression<Server> = RawReplyDefaultExpression<Server>,
|
|
241
280
|
Logger extends FastifyBaseLogger = FastifyBaseLogger,
|
|
242
281
|
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
243
|
-
> (opts: fastify.FastifyHttp2Options<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
282
|
+
> (opts: fastify.FastifyHttp2Options<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
283
|
+
TypeProvider> & SafePromiseLike<FastifyInstance<Server, Request, Reply, Logger, TypeProvider>>
|
|
244
284
|
|
|
245
285
|
declare function fastify<
|
|
246
286
|
Server extends https.Server,
|
|
@@ -248,7 +288,8 @@ declare function fastify<
|
|
|
248
288
|
Reply extends RawReplyDefaultExpression<Server> = RawReplyDefaultExpression<Server>,
|
|
249
289
|
Logger extends FastifyBaseLogger = FastifyBaseLogger,
|
|
250
290
|
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
251
|
-
> (opts: fastify.FastifyHttpsOptions<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
291
|
+
> (opts: fastify.FastifyHttpsOptions<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
292
|
+
TypeProvider> & SafePromiseLike<FastifyInstance<Server, Request, Reply, Logger, TypeProvider>>
|
|
252
293
|
|
|
253
294
|
declare function fastify<
|
|
254
295
|
Server extends http.Server,
|
|
@@ -256,7 +297,8 @@ declare function fastify<
|
|
|
256
297
|
Reply extends RawReplyDefaultExpression<Server> = RawReplyDefaultExpression<Server>,
|
|
257
298
|
Logger extends FastifyBaseLogger = FastifyBaseLogger,
|
|
258
299
|
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault
|
|
259
|
-
> (opts?: fastify.FastifyHttpOptions<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
300
|
+
> (opts?: fastify.FastifyHttpOptions<Server, Logger>): FastifyInstance<Server, Request, Reply, Logger,
|
|
301
|
+
TypeProvider> & SafePromiseLike<FastifyInstance<Server, Request, Reply, Logger, TypeProvider>>
|
|
260
302
|
|
|
261
303
|
// CJS export
|
|
262
304
|
// const fastify = require('fastify')
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '5.
|
|
3
|
+
const VERSION = '5.11.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('node:http')
|
|
@@ -143,7 +143,9 @@ function fastify (serverOptions) {
|
|
|
143
143
|
'OPTIONS',
|
|
144
144
|
'PATCH',
|
|
145
145
|
'PUT',
|
|
146
|
-
'POST'
|
|
146
|
+
'POST',
|
|
147
|
+
// RFC 10008
|
|
148
|
+
'QUERY'
|
|
147
149
|
])
|
|
148
150
|
},
|
|
149
151
|
[kOptions]: options,
|
|
@@ -200,6 +202,9 @@ function fastify (serverOptions) {
|
|
|
200
202
|
options: function _options (url, options, handler) {
|
|
201
203
|
return router.prepareRoute.call(this, { method: 'OPTIONS', url, options, handler })
|
|
202
204
|
},
|
|
205
|
+
query: function _query (url, options, handler) {
|
|
206
|
+
return router.prepareRoute.call(this, { method: 'QUERY', url, options, handler })
|
|
207
|
+
},
|
|
203
208
|
all: function _all (url, options, handler) {
|
|
204
209
|
return router.prepareRoute.call(this, { method: this.supportedMethods, url, options, handler })
|
|
205
210
|
},
|
package/lib/content-type.js
CHANGED
|
@@ -3,15 +3,37 @@
|
|
|
3
3
|
const { LruMap: Lru } = require('toad-cache')
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* keyValuePairsReg
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* keyValuePairsReg matches a single `parameter-name "=" parameter-value`
|
|
7
|
+
* at a parameter boundary, following RFC 9110 §5.6.6 grammar:
|
|
8
|
+
*
|
|
9
|
+
* parameter = parameter-name "=" parameter-value
|
|
10
|
+
* parameter-name = token
|
|
11
|
+
* parameter-value = ( token / quoted-string )
|
|
12
|
+
* quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
|
|
13
|
+
* qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text
|
|
14
|
+
* quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
|
15
|
+
* obs-text = %x80-FF
|
|
16
|
+
*
|
|
17
|
+
* The value alternative accepts either a bare token or a full quoted-string
|
|
18
|
+
* whose content matches the qdtext / quoted-pair character ranges. Because
|
|
19
|
+
* the quoted-string branch is aware of `\"` as an escape, embedded `"` and
|
|
20
|
+
* `;` characters inside a quoted value do not terminate the value.
|
|
10
21
|
*
|
|
11
22
|
* @see https://httpwg.org/specs/rfc9110.html#parameter
|
|
12
23
|
* @type {RegExp}
|
|
13
24
|
*/
|
|
14
|
-
const keyValuePairsReg = /(?:^|;)\s*([\w!#$%&'*+.^`|~-]+)=([
|
|
25
|
+
const keyValuePairsReg = /(?:^|;)\s*([\w!#$%&'*+.^`|~-]+)=("(?:[\t\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\t\u0020-\u00ff])*"|[\w!#$%&'*+.^`|~-]+)/gu
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* quotedPairReg matches a quoted-pair (a backslash followed by a single
|
|
29
|
+
* quoted-pair-allowed octet) inside a quoted-string value. Per RFC 9110
|
|
30
|
+
* §5.6.4, recipients that process the value of a quoted-string MUST handle
|
|
31
|
+
* a quoted-pair as if it were replaced by the octet following the backslash.
|
|
32
|
+
*
|
|
33
|
+
* @see https://httpwg.org/specs/rfc9110.html#quoted.string
|
|
34
|
+
* @type {RegExp}
|
|
35
|
+
*/
|
|
36
|
+
const quotedPairReg = /\\([\t\u0020-\u00ff])/gu
|
|
15
37
|
|
|
16
38
|
/**
|
|
17
39
|
* typeNameReg is used to validate that the first part of the media-type
|
|
@@ -140,21 +162,17 @@ class ContentType {
|
|
|
140
162
|
const key = matches[1].toLowerCase()
|
|
141
163
|
// Parameter values might or might not be case-sensitive,
|
|
142
164
|
// depending on the semantics of the parameter name.
|
|
143
|
-
|
|
144
|
-
if (value
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
let value = matches[2]
|
|
166
|
+
if (value.charCodeAt(0) === 0x22 /* " */) {
|
|
167
|
+
// Strip the surrounding DQUOTEs and unescape quoted-pairs per
|
|
168
|
+
// RFC 9110 §5.6.4. The regex guarantees the value starts and ends
|
|
169
|
+
// with `"` and only contains permitted qdtext / quoted-pair octets.
|
|
170
|
+
value = value.slice(1, -1)
|
|
171
|
+
if (value.indexOf('\\') !== -1) {
|
|
172
|
+
value = value.replace(quotedPairReg, '$1')
|
|
149
173
|
}
|
|
150
|
-
// We should probably verify the value matches a quoted string
|
|
151
|
-
// (https://httpwg.org/specs/rfc9110.html#rule.quoted-string) value.
|
|
152
|
-
// But we are not really doing much with the parameter values, so we
|
|
153
|
-
// are omitting that at this time.
|
|
154
|
-
this.#parameters.set(key, value.slice(1, value.length - 1))
|
|
155
|
-
} else {
|
|
156
|
-
this.#parameters.set(key, value)
|
|
157
174
|
}
|
|
175
|
+
this.#parameters.set(key, value)
|
|
158
176
|
matches = keyValuePairsReg.exec(paramsList)
|
|
159
177
|
}
|
|
160
178
|
}
|
package/lib/errors.js
CHANGED
|
@@ -455,6 +455,16 @@ const codes = {
|
|
|
455
455
|
500,
|
|
456
456
|
TypeError
|
|
457
457
|
),
|
|
458
|
+
FST_ERR_ROUTE_MISSING_CONTENT_TYPE: createError(
|
|
459
|
+
'FST_ERR_ROUTE_MISSING_CONTENT_TYPE',
|
|
460
|
+
"Method '%s' must provide a 'Content-Type' header.",
|
|
461
|
+
400
|
|
462
|
+
),
|
|
463
|
+
FST_ERR_ROUTE_MISSING_CONTENT: createError(
|
|
464
|
+
'FST_ERR_ROUTE_MISSING_CONTENT',
|
|
465
|
+
"Method '%s' must provide a request body.",
|
|
466
|
+
400
|
|
467
|
+
),
|
|
458
468
|
|
|
459
469
|
/**
|
|
460
470
|
* again listen when close server
|
package/lib/handle-request.js
CHANGED
|
@@ -4,7 +4,11 @@ const diagnostics = require('node:diagnostics_channel')
|
|
|
4
4
|
const wrapThenable = require('./wrap-thenable')
|
|
5
5
|
const { validate: validateSchema } = require('./validation')
|
|
6
6
|
const { preValidationHookRunner, preHandlerHookRunner } = require('./hooks')
|
|
7
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
FST_ERR_CTP_INVALID_MEDIA_TYPE,
|
|
9
|
+
FST_ERR_ROUTE_MISSING_CONTENT_TYPE,
|
|
10
|
+
FST_ERR_ROUTE_MISSING_CONTENT
|
|
11
|
+
} = require('./errors')
|
|
8
12
|
const { setErrorStatusCode } = require('./error-status')
|
|
9
13
|
const {
|
|
10
14
|
kReplyIsError,
|
|
@@ -37,13 +41,30 @@ function handleRequest (err, request, reply) {
|
|
|
37
41
|
const headers = request.headers
|
|
38
42
|
const ctHeader = headers['content-type']
|
|
39
43
|
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
(
|
|
44
|
+
if (method === 'QUERY') {
|
|
45
|
+
if (ctHeader === undefined) {
|
|
46
|
+
// https://datatracker.ietf.org/doc/html/rfc10008#section-2
|
|
47
|
+
// Servers MUST fail the request if the Content-Type request field
|
|
48
|
+
// ([HTTP], Section 8.3) is missing or is inconsistent with the
|
|
49
|
+
// request content.
|
|
50
|
+
reply[kReplyIsError] = true
|
|
51
|
+
reply.status(400).send(new FST_ERR_ROUTE_MISSING_CONTENT_TYPE(method))
|
|
52
|
+
return
|
|
53
|
+
}
|
|
45
54
|
|
|
46
|
-
if (isEmptyBody) {
|
|
55
|
+
if (isEmptyBody(headers)) {
|
|
56
|
+
// https://datatracker.ietf.org/doc/html/rfc10008#section-2
|
|
57
|
+
// Servers MUST fail the request if the Content-Type request field
|
|
58
|
+
// ([HTTP], Section 8.3) is missing or is inconsistent with the
|
|
59
|
+
// request content.
|
|
60
|
+
reply[kReplyIsError] = true
|
|
61
|
+
reply.status(400).send(new FST_ERR_ROUTE_MISSING_CONTENT(method))
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (ctHeader === undefined) {
|
|
67
|
+
if (isEmptyBody(headers)) {
|
|
47
68
|
// Request has no body to parse
|
|
48
69
|
handler(request, reply)
|
|
49
70
|
return
|
|
@@ -88,6 +109,13 @@ function handler (request, reply) {
|
|
|
88
109
|
}
|
|
89
110
|
}
|
|
90
111
|
|
|
112
|
+
function isEmptyBody (headers) {
|
|
113
|
+
const contentLength = headers['content-length']
|
|
114
|
+
const transferEncoding = headers['transfer-encoding']
|
|
115
|
+
return transferEncoding === undefined &&
|
|
116
|
+
(contentLength === undefined || contentLength === '0')
|
|
117
|
+
}
|
|
118
|
+
|
|
91
119
|
function preValidationCallback (err, request, reply) {
|
|
92
120
|
if (reply.sent === true) return
|
|
93
121
|
|
package/lib/hooks.js
CHANGED
|
@@ -306,7 +306,11 @@ function onSendHookRunner (functions, request, reply, payload, cb) {
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
function handleResolve (newPayload) {
|
|
309
|
-
|
|
309
|
+
try {
|
|
310
|
+
next(null, newPayload)
|
|
311
|
+
} catch (err) {
|
|
312
|
+
cb(err, request, reply, payload)
|
|
313
|
+
}
|
|
310
314
|
}
|
|
311
315
|
|
|
312
316
|
function handleReject (err) {
|