fastify 4.23.2 → 4.24.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/README.md +1 -1
- package/docs/Guides/Ecosystem.md +6 -0
- package/docs/Reference/Hooks.md +1 -0
- package/docs/Reference/Plugins.md +1 -1
- package/docs/Reference/Reply.md +4 -3
- package/docs/Reference/Request.md +3 -2
- package/docs/Reference/Server.md +31 -3
- package/docs/Reference/Type-Providers.md +2 -2
- package/docs/Reference/TypeScript.md +21 -7
- package/fastify.d.ts +2 -2
- package/fastify.js +8 -1
- package/lib/contentTypeParser.js +1 -1
- package/lib/reply.js +20 -3
- package/lib/reqIdGenFactory.js +15 -9
- package/lib/request.js +1 -1
- package/lib/route.js +18 -3
- package/lib/schemas.js +3 -3
- package/lib/warnings.js +3 -1
- package/package.json +2 -2
- package/test/async-dispose.test.js +21 -0
- package/test/constrained-routes.test.js +127 -3
- package/test/hooks-async.test.js +160 -10
- package/test/input-validation.js +3 -3
- package/test/internals/reply.test.js +33 -4
- package/test/logger/instantiation.test.js +338 -0
- package/test/logger/logger-test-utils.js +47 -0
- package/test/logger/logging.test.js +406 -0
- package/test/logger/options.test.js +500 -0
- package/test/logger/request.test.js +292 -0
- package/test/logger/response.test.js +184 -0
- package/test/reply-code.test.js +64 -0
- package/test/types/reply.test-d.ts +3 -3
- package/test/types/request.test-d.ts +9 -9
- package/test/types/type-provider.test-d.ts +89 -0
- package/test/types/using.test-d.ts +14 -0
- package/types/context.d.ts +9 -2
- package/types/instance.d.ts +4 -1
- package/types/plugin.d.ts +2 -1
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +3 -3
- package/types/route.d.ts +5 -5
- package/test/serial/logger.0.test.js +0 -866
- package/test/serial/logger.1.test.js +0 -862
- /package/test/{serial → logger}/tap-parallel-not-ok +0 -0
package/README.md
CHANGED
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -181,6 +181,8 @@ section.
|
|
|
181
181
|
to go!
|
|
182
182
|
A plugin to implement [Lyra](https://github.com/nearform/lyra) search engine
|
|
183
183
|
on Fastify
|
|
184
|
+
- [`@joggr/fastify-prisma`](https://github.com/joggrdocs/fastify-prisma)
|
|
185
|
+
A plugin for accessing an instantiated PrismaClient on your server.
|
|
184
186
|
- [`@mgcrea/fastify-graceful-exit`](https://github.com/mgcrea/fastify-graceful-exit)
|
|
185
187
|
A plugin to close the server gracefully
|
|
186
188
|
- [`@mgcrea/fastify-request-logger`](https://github.com/mgcrea/fastify-request-logger)
|
|
@@ -279,6 +281,8 @@ section.
|
|
|
279
281
|
- [`fastify-cloudevents`](https://github.com/smartiniOnGitHub/fastify-cloudevents)
|
|
280
282
|
Fastify plugin to generate and forward Fastify events in the Cloudevents
|
|
281
283
|
format.
|
|
284
|
+
- [`fastify-cloudflare-turnstile`](https://github.com/112RG/fastify-cloudflare-turnstile)
|
|
285
|
+
Fastify plugin for CloudFlare Turnstile.
|
|
282
286
|
- [`fastify-cloudinary`](https://github.com/Vanilla-IceCream/fastify-cloudinary)
|
|
283
287
|
The Cloudinary Fastify SDK allows you to quickly and easily integrate your
|
|
284
288
|
application with Cloudinary. Effortlessly optimize and transform your cloud's
|
|
@@ -317,6 +321,8 @@ section.
|
|
|
317
321
|
- [`fastify-esso`](https://github.com/patrickpissurno/fastify-esso) The easiest
|
|
318
322
|
authentication plugin for Fastify, with built-in support for Single sign-on
|
|
319
323
|
(and great documentation).
|
|
324
|
+
- [`fastify-event-bus`](https://github.com/Shiva127/fastify-event-bus) Event bus
|
|
325
|
+
support for Fastify. Built upon [js-event-bus](https://github.com/bcerati/js-event-bus).
|
|
320
326
|
- [`fastify-evervault`](https://github.com/Briscoooe/fastify-evervault/) Fastify
|
|
321
327
|
plugin for instantiating and encapsulating the
|
|
322
328
|
[Evervault](https://evervault.com/) client.
|
package/docs/Reference/Hooks.md
CHANGED
|
@@ -134,7 +134,7 @@ fastify.listen({ port: 3000 }, (err, address) => {
|
|
|
134
134
|
<a id="async-await"></a>
|
|
135
135
|
|
|
136
136
|
*async/await* is supported by `after`, `ready`, and `listen`, as well as
|
|
137
|
-
`fastify` being a
|
|
137
|
+
`fastify` being a Thenable.
|
|
138
138
|
|
|
139
139
|
```js
|
|
140
140
|
await fastify.register(require('my-plugin'))
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -85,7 +85,8 @@ object that exposes the following functions and properties:
|
|
|
85
85
|
from Node core.
|
|
86
86
|
- `.log` - The logger instance of the incoming request.
|
|
87
87
|
- `.request` - The incoming request.
|
|
88
|
-
- `.context` -
|
|
88
|
+
- `.context` - Deprecated, access the [Request's context](./Request.md) property.
|
|
89
|
+
- `.routeOptions` - Access the [Request's routeOptions](./Request.md) property.
|
|
89
90
|
|
|
90
91
|
```js
|
|
91
92
|
fastify.get('/', options, function (request, reply) {
|
|
@@ -605,8 +606,9 @@ low-level request and response. Moreover, hooks will not be invoked.
|
|
|
605
606
|
*Modifying the `.sent` property directly is deprecated. Please use the
|
|
606
607
|
aforementioned `.hijack()` method to achieve the same effect.*
|
|
607
608
|
|
|
608
|
-
<a name="hijack"></a>
|
|
609
609
|
### .hijack()
|
|
610
|
+
<a name="hijack"></a>
|
|
611
|
+
|
|
610
612
|
Sometimes you might need to halt the execution of the normal request lifecycle
|
|
611
613
|
and handle sending the response manually.
|
|
612
614
|
|
|
@@ -892,6 +894,5 @@ For more details, see:
|
|
|
892
894
|
|
|
893
895
|
- https://github.com/fastify/fastify/issues/1864 for the discussion about this
|
|
894
896
|
feature
|
|
895
|
-
- https://promisesaplus.com/ for the definition of thenables
|
|
896
897
|
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
|
|
897
898
|
for the signature
|
|
@@ -37,8 +37,9 @@ Request is a core Fastify object containing the following fields:
|
|
|
37
37
|
- `connection` - Deprecated, use `socket` instead. The underlying connection of
|
|
38
38
|
the incoming request.
|
|
39
39
|
- `socket` - the underlying connection of the incoming request
|
|
40
|
-
- `context` -
|
|
41
|
-
|
|
40
|
+
- `context` - Deprecated, use `request.routeOptions.config` instead.
|
|
41
|
+
A Fastify internal object. You should not use
|
|
42
|
+
it directly or modify it. It is useful to access one special key:
|
|
42
43
|
- `context.config` - The route [`config`](./Routes.md#routes-config) object.
|
|
43
44
|
- `routeSchema` - Deprecated, use `request.routeOptions.schema` instead. The
|
|
44
45
|
scheme definition set for the router that is handling the request
|
package/docs/Reference/Server.md
CHANGED
|
@@ -50,20 +50,21 @@ describes the properties available in that options object.
|
|
|
50
50
|
- [after](#after)
|
|
51
51
|
- [ready](#ready)
|
|
52
52
|
- [listen](#listen)
|
|
53
|
+
- [`listenTextResolver`](#listentextresolver)
|
|
53
54
|
- [addresses](#addresses)
|
|
54
55
|
- [getDefaultRoute](#getdefaultroute)
|
|
55
56
|
- [setDefaultRoute](#setdefaultroute)
|
|
56
57
|
- [routing](#routing)
|
|
57
58
|
- [route](#route)
|
|
58
|
-
- [hasRoute](#
|
|
59
|
+
- [hasRoute](#hasroute)
|
|
59
60
|
- [close](#close)
|
|
60
|
-
- [decorate
|
|
61
|
+
- [decorate\*](#decorate)
|
|
61
62
|
- [register](#register)
|
|
62
63
|
- [addHook](#addhook)
|
|
63
64
|
- [prefix](#prefix)
|
|
64
65
|
- [pluginName](#pluginname)
|
|
65
66
|
- [hasPlugin](#hasplugin)
|
|
66
|
-
|
|
67
|
+
- [listeningOrigin](#listeningorigin)
|
|
67
68
|
- [log](#log)
|
|
68
69
|
- [version](#version)
|
|
69
70
|
- [inject](#inject)
|
|
@@ -93,6 +94,7 @@ describes the properties available in that options object.
|
|
|
93
94
|
- [defaultTextParser](#defaulttextparser)
|
|
94
95
|
- [errorHandler](#errorhandler)
|
|
95
96
|
- [childLoggerFactory](#childloggerfactory)
|
|
97
|
+
- [Symbol.asyncDispose](#symbolasyncdispose)
|
|
96
98
|
- [initialConfig](#initialconfig)
|
|
97
99
|
|
|
98
100
|
### `http`
|
|
@@ -1866,6 +1868,32 @@ fastify.get('/', {
|
|
|
1866
1868
|
Fastify instance. See the [`childLoggerFactory` config option](#setchildloggerfactory)
|
|
1867
1869
|
for more info.
|
|
1868
1870
|
|
|
1871
|
+
#### Symbol.asyncDispose
|
|
1872
|
+
<a id="symbolAsyncDispose"></a>
|
|
1873
|
+
|
|
1874
|
+
`fastify[Symbol.asyncDispose]` is a symbol that can be used to define an
|
|
1875
|
+
asynchronous function that will be called when the Fastify instance is closed.
|
|
1876
|
+
|
|
1877
|
+
It's commonly used alongside the `using` TypeScript keyword to ensure that
|
|
1878
|
+
resources are cleaned up when the Fastify instance is closed.
|
|
1879
|
+
|
|
1880
|
+
This combines perfectly inside short lived processes or unit tests, where you must
|
|
1881
|
+
close all Fastify resources after returning from inside the function.
|
|
1882
|
+
|
|
1883
|
+
```ts
|
|
1884
|
+
test('Uses app and closes it afterwards', async () => {
|
|
1885
|
+
await using app = fastify();
|
|
1886
|
+
// do something with app.
|
|
1887
|
+
})
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
In the above example, Fastify is closed automatically after the test finishes.
|
|
1891
|
+
|
|
1892
|
+
Read more about the
|
|
1893
|
+
[ECMAScript Explicit Resource Management](https://tc39.es/proposal-explicit-resource-management)
|
|
1894
|
+
and the [using keyword](https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/)
|
|
1895
|
+
introduced in TypeScript 5.2.
|
|
1896
|
+
|
|
1869
1897
|
#### initialConfig
|
|
1870
1898
|
<a id="initial-config"></a>
|
|
1871
1899
|
|
|
@@ -47,7 +47,7 @@ server.get('/route', {
|
|
|
47
47
|
},
|
|
48
48
|
required: ['foo', 'bar']
|
|
49
49
|
}
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
51
|
|
|
52
52
|
}, (request, reply) => {
|
|
53
53
|
|
|
@@ -141,7 +141,7 @@ function pluginWithJsonSchema(fastify: FastifyInstance, _opts, done): void {
|
|
|
141
141
|
y: { type: 'number' },
|
|
142
142
|
z: { type: 'boolean' }
|
|
143
143
|
},
|
|
144
|
-
}
|
|
144
|
+
}
|
|
145
145
|
}
|
|
146
146
|
}, (req) => {
|
|
147
147
|
const { x, y, z } = req.body // type safe
|
|
@@ -606,7 +606,7 @@ your plugin.
|
|
|
606
606
|
```
|
|
607
607
|
5. Open `index.d.ts` and add the following code:
|
|
608
608
|
```typescript
|
|
609
|
-
import {
|
|
609
|
+
import { FastifyPluginCallback } from 'fastify'
|
|
610
610
|
|
|
611
611
|
interface PluginOptions {
|
|
612
612
|
//...
|
|
@@ -627,7 +627,7 @@ your plugin.
|
|
|
627
627
|
|
|
628
628
|
// fastify-plugin automatically adds named export, so be sure to add also this type
|
|
629
629
|
// the variable name is derived from `options.name` property if `module.exports.myPlugin` is missing
|
|
630
|
-
export const myPlugin:
|
|
630
|
+
export const myPlugin: FastifyPluginCallback<PluginOptions>
|
|
631
631
|
|
|
632
632
|
// fastify-plugin automatically adds `.default` property to the exported plugin. See the note below
|
|
633
633
|
export default myPlugin
|
|
@@ -1233,15 +1233,16 @@ a function signature with an underlying generic `Options` which is defaulted to
|
|
|
1233
1233
|
FastifyPlugin parameter when calling this function so there is no need to
|
|
1234
1234
|
specify the underlying generic. The options parameter is the intersection of the
|
|
1235
1235
|
plugin's options and two additional optional properties: `prefix: string` and
|
|
1236
|
-
`logLevel`: [LogLevel][LogLevel].
|
|
1236
|
+
`logLevel`: [LogLevel][LogLevel]. `FastifyPlugin` is deprecated use
|
|
1237
|
+
`FastifyPluginCallback` and `FastifyPluginAsync` instead.
|
|
1237
1238
|
|
|
1238
1239
|
Below is an example of the options inference in action:
|
|
1239
1240
|
|
|
1240
1241
|
```typescript
|
|
1241
1242
|
const server = fastify()
|
|
1242
1243
|
|
|
1243
|
-
const plugin:
|
|
1244
|
-
option1: string;
|
|
1244
|
+
const plugin: FastifyPluginCallback<{
|
|
1245
|
+
: option1: string;
|
|
1245
1246
|
option2: boolean;
|
|
1246
1247
|
}> = function (instance, opts, done) { }
|
|
1247
1248
|
|
|
@@ -1296,9 +1297,22 @@ Union type of: `'info' | 'error' | 'debug' | 'fatal' | 'warn' | 'trace'`
|
|
|
1296
1297
|
The context type definition is similar to the other highly dynamic pieces of the
|
|
1297
1298
|
type system. Route context is available in the route handler method.
|
|
1298
1299
|
|
|
1299
|
-
##### fastify.
|
|
1300
|
+
##### fastify.FastifyRequestContext
|
|
1300
1301
|
|
|
1301
|
-
[src](https://github.com/fastify/fastify/blob/main/types/context.d.ts#
|
|
1302
|
+
[src](https://github.com/fastify/fastify/blob/main/types/context.d.ts#L11)
|
|
1303
|
+
|
|
1304
|
+
An interface with a single required property `config` that is set by default to
|
|
1305
|
+
`unknown`. Can be specified either using a generic or an overload.
|
|
1306
|
+
|
|
1307
|
+
This type definition is potentially incomplete. If you are using it and can
|
|
1308
|
+
provide more details on how to improve the definition, we strongly encourage you
|
|
1309
|
+
to open an issue in the main
|
|
1310
|
+
[fastify/fastify](https://github.com/fastify/fastify) repository. Thank you in
|
|
1311
|
+
advanced!
|
|
1312
|
+
|
|
1313
|
+
##### fastify.FastifyReplyContext
|
|
1314
|
+
|
|
1315
|
+
[src](https://github.com/fastify/fastify/blob/main/types/context.d.ts#L11)
|
|
1302
1316
|
|
|
1303
1317
|
An interface with a single required property `config` that is set by default to
|
|
1304
1318
|
`unknown`. Can be specified either using a generic or an overload.
|
package/fastify.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { ConstraintStrategy, HTTPVersion } from 'find-my-way'
|
|
|
10
10
|
import { Chain as LightMyRequestChain, InjectOptions, Response as LightMyRequestResponse, CallbackFunc as LightMyRequestCallback } from 'light-my-request'
|
|
11
11
|
|
|
12
12
|
import { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction } from './types/content-type-parser'
|
|
13
|
-
import {
|
|
13
|
+
import { FastifyRequestContext, FastifyContextConfig, FastifyReplyContext } from './types/context'
|
|
14
14
|
import { FastifyErrorCodes } from './types/errors'
|
|
15
15
|
import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onListenAsyncHookHandler, onListenHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler } from './types/hooks'
|
|
16
16
|
import { FastifyListenOptions, FastifyInstance, PrintRoutesOptions } from './types/instance'
|
|
@@ -175,7 +175,7 @@ declare namespace fastify {
|
|
|
175
175
|
FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin, // './types/plugin'
|
|
176
176
|
FastifyListenOptions, FastifyInstance, PrintRoutesOptions, // './types/instance'
|
|
177
177
|
FastifyLoggerOptions, FastifyBaseLogger, FastifyLoggerInstance, FastifyLogFn, LogLevel, // './types/logger'
|
|
178
|
-
|
|
178
|
+
FastifyRequestContext, FastifyContextConfig, FastifyReplyContext, // './types/context'
|
|
179
179
|
RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler, RouteGenericInterface, // './types/route'
|
|
180
180
|
FastifyRegister, FastifyRegisterOptions, RegisterOptions, // './types/register'
|
|
181
181
|
FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction, // './types/content-type-parser'
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.24.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('node:http')
|
|
@@ -506,6 +506,13 @@ function fastify (options) {
|
|
|
506
506
|
// versions of Node.js. In that event, we don't care, so ignore the error.
|
|
507
507
|
}
|
|
508
508
|
|
|
509
|
+
// Older nodejs versions may not have asyncDispose
|
|
510
|
+
if ('asyncDispose' in Symbol) {
|
|
511
|
+
fastify[Symbol.asyncDispose] = function dispose () {
|
|
512
|
+
return fastify.close()
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
509
516
|
return fastify
|
|
510
517
|
|
|
511
518
|
function throwIfAlreadyStarted (msg) {
|
package/lib/contentTypeParser.js
CHANGED
|
@@ -406,7 +406,7 @@ function ParserListItem (contentType) {
|
|
|
406
406
|
// because it would become a match-all handler
|
|
407
407
|
if (this.isEssence === false && parsed.type === '') {
|
|
408
408
|
// handle semicolon or empty string
|
|
409
|
-
const tmp = contentType.split(';')[0]
|
|
409
|
+
const tmp = contentType.split(';', 1)[0]
|
|
410
410
|
this.type = tmp === '' ? contentType : tmp
|
|
411
411
|
} else {
|
|
412
412
|
this.type = parsed.type
|
package/lib/reply.js
CHANGED
|
@@ -4,6 +4,7 @@ const eos = require('node:stream').finished
|
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
6
|
kFourOhFourContext,
|
|
7
|
+
kPublicRouteContext,
|
|
7
8
|
kReplyErrorHandlerCalled,
|
|
8
9
|
kReplyHijacked,
|
|
9
10
|
kReplyStartTime,
|
|
@@ -79,6 +80,7 @@ Object.defineProperties(Reply.prototype, {
|
|
|
79
80
|
// Is temporary to avoid constant conflicts between `next` and `main`
|
|
80
81
|
context: {
|
|
81
82
|
get () {
|
|
83
|
+
warning.emit('FSTDEP019')
|
|
82
84
|
return this.request[kRouteContext]
|
|
83
85
|
}
|
|
84
86
|
},
|
|
@@ -115,6 +117,11 @@ Object.defineProperties(Reply.prototype, {
|
|
|
115
117
|
set (value) {
|
|
116
118
|
this.code(value)
|
|
117
119
|
}
|
|
120
|
+
},
|
|
121
|
+
[kPublicRouteContext]: {
|
|
122
|
+
get () {
|
|
123
|
+
return this.request[kPublicRouteContext]
|
|
124
|
+
}
|
|
118
125
|
}
|
|
119
126
|
})
|
|
120
127
|
|
|
@@ -244,7 +251,7 @@ Reply.prototype.header = function (key, value = '') {
|
|
|
244
251
|
}
|
|
245
252
|
|
|
246
253
|
if (Array.isArray(value)) {
|
|
247
|
-
this[kReplyHeaders][key]
|
|
254
|
+
Array.prototype.push.apply(this[kReplyHeaders][key], value)
|
|
248
255
|
} else {
|
|
249
256
|
this[kReplyHeaders][key].push(value)
|
|
250
257
|
}
|
|
@@ -458,7 +465,6 @@ Reply.prototype.getResponseTime = function () {
|
|
|
458
465
|
// Make reply a thenable, so it could be used with async/await.
|
|
459
466
|
// See
|
|
460
467
|
// - https://github.com/fastify/fastify/issues/1864 for the discussions
|
|
461
|
-
// - https://promisesaplus.com/ for the definition of thenable
|
|
462
468
|
// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then for the signature
|
|
463
469
|
Reply.prototype.then = function (fulfilled, rejected) {
|
|
464
470
|
if (this.sent) {
|
|
@@ -591,6 +597,17 @@ function onSendEnd (reply, payload) {
|
|
|
591
597
|
return
|
|
592
598
|
}
|
|
593
599
|
|
|
600
|
+
if ((statusCode >= 100 && statusCode < 200) || statusCode === 204) {
|
|
601
|
+
// Responses without a content body must not send content-type
|
|
602
|
+
// or content-length headers.
|
|
603
|
+
// See https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6.
|
|
604
|
+
reply.removeHeader('content-type')
|
|
605
|
+
reply.removeHeader('content-length')
|
|
606
|
+
safeWriteHead(reply, statusCode)
|
|
607
|
+
sendTrailer(undefined, res, reply)
|
|
608
|
+
return
|
|
609
|
+
}
|
|
610
|
+
|
|
594
611
|
if (typeof payload.pipe === 'function') {
|
|
595
612
|
sendStream(payload, res, reply)
|
|
596
613
|
return
|
|
@@ -810,7 +827,7 @@ function onResponseCallback (err, request, reply) {
|
|
|
810
827
|
}
|
|
811
828
|
|
|
812
829
|
function buildReply (R) {
|
|
813
|
-
const props =
|
|
830
|
+
const props = R.props.slice()
|
|
814
831
|
|
|
815
832
|
function _Reply (res, request, log) {
|
|
816
833
|
this.raw = res
|
package/lib/reqIdGenFactory.js
CHANGED
|
@@ -12,6 +12,16 @@
|
|
|
12
12
|
* @returns {GenerateRequestId}
|
|
13
13
|
*/
|
|
14
14
|
function reqIdGenFactory (requestIdHeader, optGenReqId) {
|
|
15
|
+
const genReqId = optGenReqId || buildDefaultGenReqId()
|
|
16
|
+
|
|
17
|
+
if (requestIdHeader) {
|
|
18
|
+
return buildOptionalHeaderReqId(requestIdHeader, genReqId)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return genReqId
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function buildDefaultGenReqId () {
|
|
15
25
|
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).
|
|
16
26
|
// With this upper bound, if you'll be generating 1k ids/sec, you're going to hit it in ~25 days.
|
|
17
27
|
// This is very likely to happen in real-world applications, hence the limit is enforced.
|
|
@@ -20,20 +30,16 @@ function reqIdGenFactory (requestIdHeader, optGenReqId) {
|
|
|
20
30
|
const maxInt = 2147483647
|
|
21
31
|
|
|
22
32
|
let nextReqId = 0
|
|
23
|
-
function defaultGenReqId (
|
|
33
|
+
return function defaultGenReqId () {
|
|
24
34
|
nextReqId = (nextReqId + 1) & maxInt
|
|
25
35
|
return `req-${nextReqId.toString(36)}`
|
|
26
36
|
}
|
|
37
|
+
}
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return function (req) {
|
|
32
|
-
return req.headers[requestIdHeader] || genReqId(req)
|
|
33
|
-
}
|
|
39
|
+
function buildOptionalHeaderReqId (requestIdHeader, genReqId) {
|
|
40
|
+
return function (req) {
|
|
41
|
+
return req.headers[requestIdHeader] || genReqId(req)
|
|
34
42
|
}
|
|
35
|
-
|
|
36
|
-
return genReqId
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
module.exports = {
|
package/lib/request.js
CHANGED
package/lib/route.js
CHANGED
|
@@ -28,7 +28,8 @@ const {
|
|
|
28
28
|
FST_ERR_ROUTE_METHOD_NOT_SUPPORTED,
|
|
29
29
|
FST_ERR_ROUTE_METHOD_INVALID,
|
|
30
30
|
FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED,
|
|
31
|
-
FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT
|
|
31
|
+
FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT,
|
|
32
|
+
FST_ERR_HOOK_INVALID_ASYNC_HANDLER
|
|
32
33
|
} = require('./errors')
|
|
33
34
|
|
|
34
35
|
const {
|
|
@@ -268,6 +269,20 @@ function buildRouting (options) {
|
|
|
268
269
|
if (typeof func !== 'function') {
|
|
269
270
|
throw new FST_ERR_HOOK_INVALID_HANDLER(hook, Object.prototype.toString.call(func))
|
|
270
271
|
}
|
|
272
|
+
|
|
273
|
+
if (hook === 'onSend' || hook === 'preSerialization' || hook === 'onError' || hook === 'preParsing') {
|
|
274
|
+
if (func.constructor.name === 'AsyncFunction' && func.length === 4) {
|
|
275
|
+
throw new FST_ERR_HOOK_INVALID_ASYNC_HANDLER()
|
|
276
|
+
}
|
|
277
|
+
} else if (hook === 'onRequestAbort') {
|
|
278
|
+
if (func.constructor.name === 'AsyncFunction' && func.length !== 1) {
|
|
279
|
+
throw new FST_ERR_HOOK_INVALID_ASYNC_HANDLER()
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
if (func.constructor.name === 'AsyncFunction' && func.length === 3) {
|
|
283
|
+
throw new FST_ERR_HOOK_INVALID_ASYNC_HANDLER()
|
|
284
|
+
}
|
|
285
|
+
}
|
|
271
286
|
}
|
|
272
287
|
} else if (opts[hook] !== undefined && typeof opts[hook] !== 'function') {
|
|
273
288
|
throw new FST_ERR_HOOK_INVALID_HANDLER(hook, Object.prototype.toString.call(opts[hook]))
|
|
@@ -307,8 +322,8 @@ function buildRouting (options) {
|
|
|
307
322
|
constraints.version = opts.version
|
|
308
323
|
}
|
|
309
324
|
|
|
310
|
-
const headHandler = router.
|
|
311
|
-
const hasHEADHandler = headHandler
|
|
325
|
+
const headHandler = router.findRoute('HEAD', opts.url, constraints)
|
|
326
|
+
const hasHEADHandler = headHandler !== null
|
|
312
327
|
|
|
313
328
|
// remove the head route created by fastify
|
|
314
329
|
if (hasHEADHandler && !context[kRouteByFastify] && headHandler.store[kRouteByFastify]) {
|
package/lib/schemas.js
CHANGED
|
@@ -158,7 +158,7 @@ function getSchemaSerializer (context, statusCode, contentType) {
|
|
|
158
158
|
}
|
|
159
159
|
if (responseSchemaDef[statusCode]) {
|
|
160
160
|
if (responseSchemaDef[statusCode].constructor === Object && contentType) {
|
|
161
|
-
const mediaName = contentType.split(';')[0]
|
|
161
|
+
const mediaName = contentType.split(';', 1)[0]
|
|
162
162
|
if (responseSchemaDef[statusCode][mediaName]) {
|
|
163
163
|
return responseSchemaDef[statusCode][mediaName]
|
|
164
164
|
}
|
|
@@ -170,7 +170,7 @@ function getSchemaSerializer (context, statusCode, contentType) {
|
|
|
170
170
|
const fallbackStatusCode = (statusCode + '')[0] + 'xx'
|
|
171
171
|
if (responseSchemaDef[fallbackStatusCode]) {
|
|
172
172
|
if (responseSchemaDef[fallbackStatusCode].constructor === Object && contentType) {
|
|
173
|
-
const mediaName = contentType.split(';')[0]
|
|
173
|
+
const mediaName = contentType.split(';', 1)[0]
|
|
174
174
|
if (responseSchemaDef[fallbackStatusCode][mediaName]) {
|
|
175
175
|
return responseSchemaDef[fallbackStatusCode][mediaName]
|
|
176
176
|
}
|
|
@@ -182,7 +182,7 @@ function getSchemaSerializer (context, statusCode, contentType) {
|
|
|
182
182
|
}
|
|
183
183
|
if (responseSchemaDef.default) {
|
|
184
184
|
if (responseSchemaDef.default.constructor === Object && contentType) {
|
|
185
|
-
const mediaName = contentType.split(';')[0]
|
|
185
|
+
const mediaName = contentType.split(';', 1)[0]
|
|
186
186
|
if (responseSchemaDef.default[mediaName]) {
|
|
187
187
|
return responseSchemaDef.default[mediaName]
|
|
188
188
|
}
|
package/lib/warnings.js
CHANGED
|
@@ -21,7 +21,7 @@ warning.create('FastifyDeprecation', 'FSTDEP010', 'Modifying the "reply.sent" pr
|
|
|
21
21
|
|
|
22
22
|
warning.create('FastifyDeprecation', 'FSTDEP011', 'Variadic listen method is deprecated. Please use ".listen(optionsObject)" instead. The variadic signature will be removed in `fastify@5`.')
|
|
23
23
|
|
|
24
|
-
warning.create('FastifyDeprecation', 'FSTDEP012', '
|
|
24
|
+
warning.create('FastifyDeprecation', 'FSTDEP012', 'request.context property access is deprecated. Please use "request.routeOptions.config" or "request.routeOptions.schema" instead for accessing Route settings. The "request.context" will be removed in `fastify@5`.')
|
|
25
25
|
|
|
26
26
|
warning.create('FastifyDeprecation', 'FSTDEP013', 'Direct return of "trailers" function is deprecated. Please use "callback" or "async-await" for return value. The support of direct return will removed in `fastify@5`.')
|
|
27
27
|
|
|
@@ -35,6 +35,8 @@ warning.create('FastifyDeprecation', 'FSTDEP017', 'You are accessing the depreca
|
|
|
35
35
|
|
|
36
36
|
warning.create('FastifyDeprecation', 'FSTDEP018', 'You are accessing the deprecated "request.routerMethod" property. Use "request.routeOptions.method" instead. Property "req.routerMethod" will be removed in `fastify@5`.')
|
|
37
37
|
|
|
38
|
+
warning.create('FastifyDeprecation', 'FSTDEP019', 'reply.context property access is deprecated. Please use "reply.routeOptions.config" or "reply.routeOptions.schema" instead for accessing Route settings. The "reply.context" will be removed in `fastify@5`.')
|
|
39
|
+
|
|
38
40
|
warning.create('FastifyWarning', 'FSTWRN001', 'The %s schema for %s: %s is missing. This may indicate the schema is not well specified.', { unlimited: true })
|
|
39
41
|
|
|
40
42
|
module.exports = warning
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.0",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
"avvio": "^8.2.1",
|
|
196
196
|
"fast-content-type-parse": "^1.0.0",
|
|
197
197
|
"fast-json-stringify": "^5.7.0",
|
|
198
|
-
"find-my-way": "^7.
|
|
198
|
+
"find-my-way": "^7.7.0",
|
|
199
199
|
"light-my-request": "^5.9.1",
|
|
200
200
|
"pino": "^8.12.0",
|
|
201
201
|
"process-warning": "^2.2.0",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const Fastify = require('../fastify')
|
|
5
|
+
|
|
6
|
+
// asyncDispose doesn't exist in node <= 16
|
|
7
|
+
t.test('async dispose should close fastify', { skip: !('asyncDispose' in Symbol) }, async t => {
|
|
8
|
+
t.plan(2)
|
|
9
|
+
|
|
10
|
+
const fastify = Fastify()
|
|
11
|
+
|
|
12
|
+
await fastify.listen({ port: 0 })
|
|
13
|
+
|
|
14
|
+
t.equal(fastify.server.listening, true)
|
|
15
|
+
|
|
16
|
+
// the same as syntax sugar for
|
|
17
|
+
// await using app = fastify()
|
|
18
|
+
await fastify[Symbol.asyncDispose]()
|
|
19
|
+
|
|
20
|
+
t.equal(fastify.server.listening, false)
|
|
21
|
+
})
|