fastify 4.25.2 → 4.26.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/.vscode/settings.json +22 -0
- package/EXPENSE_POLICY.md +105 -0
- package/GOVERNANCE.md +2 -103
- package/LICENSE +1 -1
- package/README.md +13 -9
- package/SECURITY.md +2 -157
- package/SPONSORS.md +20 -0
- package/build/build-validation.js +3 -1
- package/docs/Guides/Ecosystem.md +27 -9
- package/docs/Guides/Getting-Started.md +16 -3
- package/docs/Guides/Style-Guide.md +7 -7
- package/docs/Reference/Decorators.md +1 -1
- package/docs/Reference/Errors.md +63 -1
- package/docs/Reference/Hooks.md +1 -1
- package/docs/Reference/Logging.md +3 -3
- package/docs/Reference/Reply.md +70 -1
- package/docs/Reference/Server.md +90 -0
- package/docs/Reference/Warnings.md +2 -0
- package/fastify.d.ts +3 -2
- package/fastify.js +25 -7
- package/lib/configValidator.js +62 -33
- package/lib/contentTypeParser.js +9 -2
- package/lib/error-handler.js +1 -1
- package/lib/error-serializer.js +2 -0
- package/lib/errors.js +4 -0
- package/lib/fourOhFour.js +4 -3
- package/lib/hooks.js +1 -5
- package/lib/reply.js +68 -10
- package/lib/reqIdGenFactory.js +5 -0
- package/lib/route.js +22 -6
- package/lib/schema-controller.js +37 -4
- package/lib/symbols.js +1 -0
- package/lib/warnings.js +6 -0
- package/package.json +17 -5
- package/test/async_hooks.test.js +69 -0
- package/test/findRoute.test.js +135 -0
- package/test/genReqId.test.js +392 -0
- package/test/hooks.on-listen.test.js +66 -14
- package/test/internals/errors.test.js +17 -7
- package/test/internals/initialConfig.test.js +7 -3
- package/test/internals/reply.test.js +80 -5
- package/test/schema-serialization.test.js +41 -0
- package/test/schema-validation.test.js +115 -6
- package/test/serialize-response.test.js +187 -0
- package/test/types/instance.test-d.ts +14 -1
- package/test/types/reply.test-d.ts +4 -2
- package/test/types/route.test-d.ts +15 -1
- package/test/useSemicolonDelimiter.test.js +113 -0
- package/test/web-api.test.js +208 -0
- package/types/instance.d.ts +23 -10
- package/types/reply.d.ts +4 -0
- package/test/types/import.js +0 -2
|
@@ -55,6 +55,14 @@ fastify.listen({ port: 3000 }, function (err, address) {
|
|
|
55
55
|
})
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
> If you are using ECMAScript Modules (ESM) in your project, be sure to
|
|
59
|
+
> include "type": "module" in your package.json.
|
|
60
|
+
>```js
|
|
61
|
+
>{
|
|
62
|
+
> "type": "module"
|
|
63
|
+
>}
|
|
64
|
+
>```
|
|
65
|
+
|
|
58
66
|
Do you prefer to use `async/await`? Fastify supports it out-of-the-box.
|
|
59
67
|
|
|
60
68
|
```js
|
|
@@ -172,13 +180,14 @@ fastify.listen({ port: 3000 }, function (err, address) {
|
|
|
172
180
|
})
|
|
173
181
|
```
|
|
174
182
|
|
|
183
|
+
|
|
175
184
|
```js
|
|
176
185
|
// our-first-route.js
|
|
177
186
|
|
|
178
187
|
/**
|
|
179
188
|
* Encapsulates the routes
|
|
180
189
|
* @param {FastifyInstance} fastify Encapsulated Fastify Instance
|
|
181
|
-
* @param {Object} options plugin options, refer to https://
|
|
190
|
+
* @param {Object} options plugin options, refer to https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options
|
|
182
191
|
*/
|
|
183
192
|
async function routes (fastify, options) {
|
|
184
193
|
fastify.get('/', async (request, reply) => {
|
|
@@ -186,6 +195,10 @@ async function routes (fastify, options) {
|
|
|
186
195
|
})
|
|
187
196
|
}
|
|
188
197
|
|
|
198
|
+
//ESM
|
|
199
|
+
export default routes;
|
|
200
|
+
|
|
201
|
+
// CommonJs
|
|
189
202
|
module.exports = routes
|
|
190
203
|
```
|
|
191
204
|
In this example, we used the `register` API, which is the core of the Fastify
|
|
@@ -293,7 +306,7 @@ const fastifyPlugin = require('fastify-plugin')
|
|
|
293
306
|
/**
|
|
294
307
|
* Connects to a MongoDB database
|
|
295
308
|
* @param {FastifyInstance} fastify Encapsulated Fastify Instance
|
|
296
|
-
* @param {Object} options plugin options, refer to https://
|
|
309
|
+
* @param {Object} options plugin options, refer to https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options
|
|
297
310
|
*/
|
|
298
311
|
async function dbConnector (fastify, options) {
|
|
299
312
|
fastify.register(require('@fastify/mongodb'), {
|
|
@@ -312,7 +325,7 @@ module.exports = fastifyPlugin(dbConnector)
|
|
|
312
325
|
/**
|
|
313
326
|
* A plugin that provide encapsulated routes
|
|
314
327
|
* @param {FastifyInstance} fastify encapsulated fastify instance
|
|
315
|
-
* @param {Object} options plugin options, refer to https://
|
|
328
|
+
* @param {Object} options plugin options, refer to https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options
|
|
316
329
|
*/
|
|
317
330
|
async function routes (fastify, options) {
|
|
318
331
|
const collection = fastify.mongo.db.collection('test_collection')
|
|
@@ -13,7 +13,7 @@ This guide is for anyone who loves to build with Fastify or wants to contribute
|
|
|
13
13
|
to our documentation. You do not need to be an expert in writing technical
|
|
14
14
|
documentation. This guide is here to help you.
|
|
15
15
|
|
|
16
|
-
Visit the [contribute](https://
|
|
16
|
+
Visit the [contribute](https://fastify.dev/contribute) page on our website or
|
|
17
17
|
read the
|
|
18
18
|
[CONTRIBUTING.md](https://github.com/fastify/fastify/blob/main/CONTRIBUTING.md)
|
|
19
19
|
file on GitHub to join our Open Source folks.
|
|
@@ -70,12 +70,12 @@ markdown.
|
|
|
70
70
|
**Example**
|
|
71
71
|
|
|
72
72
|
```
|
|
73
|
-
To learn more about hooks, see [Fastify hooks](https://
|
|
73
|
+
To learn more about hooks, see [Fastify hooks](https://fastify.dev/docs/latest/Reference/Hooks/).
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
Result:
|
|
77
77
|
>To learn more about hooks, see [Fastify
|
|
78
|
-
>hooks](https://
|
|
78
|
+
>hooks](https://fastify.dev/docs/latest/Reference/Hooks/).
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
|
|
@@ -224,18 +224,18 @@ hyperlink should look:
|
|
|
224
224
|
<!-- More like this -->
|
|
225
225
|
|
|
226
226
|
// Add clear & brief description
|
|
227
|
-
[Fastify Plugins] (https://
|
|
227
|
+
[Fastify Plugins] (https://fastify.dev/docs/latest/Plugins/)
|
|
228
228
|
|
|
229
229
|
<!--Less like this -->
|
|
230
230
|
|
|
231
231
|
// incomplete description
|
|
232
|
-
[Fastify] (https://
|
|
232
|
+
[Fastify] (https://fastify.dev/docs/latest/Plugins/)
|
|
233
233
|
|
|
234
234
|
// Adding title in link brackets
|
|
235
|
-
[](https://
|
|
235
|
+
[](https://fastify.dev/docs/latest/Plugins/ "fastify plugin")
|
|
236
236
|
|
|
237
237
|
// Empty title
|
|
238
|
-
[](https://
|
|
238
|
+
[](https://fastify.dev/docs/latest/Plugins/)
|
|
239
239
|
|
|
240
240
|
// Adding links localhost URLs instead of using code strings (``)
|
|
241
241
|
[http://localhost:3000/](http://localhost:3000/)
|
package/docs/Reference/Errors.md
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
- [FST_ERR_LOG_INVALID_DESTINATION](#fst_err_log_invalid_destination)
|
|
46
46
|
- [FST_ERR_LOG_INVALID_LOGGER](#fst_err_log_invalid_logger)
|
|
47
47
|
- [FST_ERR_REP_INVALID_PAYLOAD_TYPE](#fst_err_rep_invalid_payload_type)
|
|
48
|
+
- [FST_ERR_REP_RESPONSE_BODY_CONSUMED](#fst_err_rep_response_body_consumed)
|
|
48
49
|
- [FST_ERR_REP_ALREADY_SENT](#fst_err_rep_already_sent)
|
|
49
50
|
- [FST_ERR_REP_SENT_VALUE](#fst_err_rep_sent_value)
|
|
50
51
|
- [FST_ERR_SEND_INSIDE_ONERR](#fst_err_send_inside_onerr)
|
|
@@ -169,6 +170,65 @@ Some things to consider in your custom error handler:
|
|
|
169
170
|
internally monitors the error invocation to avoid infinite loops for errors
|
|
170
171
|
thrown in the reply phases of the lifecycle. (those after the route handler)
|
|
171
172
|
|
|
173
|
+
When utilizing Fastify's custom error handling through [`setErrorHandler`](./Server.md#seterrorhandler),
|
|
174
|
+
you should be aware of how errors are propagated between custom and default
|
|
175
|
+
error handlers.
|
|
176
|
+
|
|
177
|
+
If a plugin's error handler re-throws an error, and the error is not an
|
|
178
|
+
instance of [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
|
179
|
+
(as seen in the `/bad` route in the following example), it will not propagate
|
|
180
|
+
to the parent context error handler. Instead, it will be caught by the default
|
|
181
|
+
error handler.
|
|
182
|
+
|
|
183
|
+
To ensure consistent error handling, it is recommended to throw instances of
|
|
184
|
+
`Error`. For instance, in the following example, replacing `throw 'foo'` with
|
|
185
|
+
`throw new Error('foo')` in the `/bad` route ensures that errors propagate through
|
|
186
|
+
the custom error handling chain as intended. This practice helps avoid potential
|
|
187
|
+
pitfalls when working with custom error handling in Fastify.
|
|
188
|
+
|
|
189
|
+
For example:
|
|
190
|
+
```js
|
|
191
|
+
const Fastify = require('fastify')
|
|
192
|
+
|
|
193
|
+
// Instantiate the framework
|
|
194
|
+
const fastify = Fastify({
|
|
195
|
+
logger: true
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Register parent error handler
|
|
199
|
+
fastify.setErrorHandler((error, request, reply) => {
|
|
200
|
+
reply.status(500).send({ ok: false })
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
fastify.register((app, options, next) => {
|
|
204
|
+
// Register child error handler
|
|
205
|
+
fastify.setErrorHandler((error, request, reply) => {
|
|
206
|
+
throw error
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
fastify.get('/bad', async () => {
|
|
210
|
+
// Throws a non-Error type, 'bar'
|
|
211
|
+
throw 'foo'
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
fastify.get('/good', async () => {
|
|
215
|
+
// Throws an Error instance, 'bar'
|
|
216
|
+
throw new Error('bar')
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
next()
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
// Run the server
|
|
223
|
+
fastify.listen({ port: 3000 }, function (err, address) {
|
|
224
|
+
if (err) {
|
|
225
|
+
fastify.log.error(err)
|
|
226
|
+
process.exit(1)
|
|
227
|
+
}
|
|
228
|
+
// Server is listening at ${address}
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
172
232
|
### Fastify Error Codes
|
|
173
233
|
<a id="fastify-error-codes"></a>
|
|
174
234
|
|
|
@@ -183,7 +243,7 @@ const errorCodes = require('fastify').errorCodes
|
|
|
183
243
|
|
|
184
244
|
For example:
|
|
185
245
|
```js
|
|
186
|
-
const Fastify = require('
|
|
246
|
+
const Fastify = require('fastify')
|
|
187
247
|
|
|
188
248
|
// Instantiate the framework
|
|
189
249
|
const fastify = Fastify({
|
|
@@ -253,6 +313,8 @@ Below is a table with all the error codes that Fastify uses.
|
|
|
253
313
|
| <a id="fst_err_log_invalid_destination">FST_ERR_LOG_INVALID_DESTINATION</a> | The logger does not accept the specified destination. | Use a `'stream'` or a `'file'` as the destination. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
|
254
314
|
| <a id="fst_err_log_invalid_logger">FST_ERR_LOG_INVALID_LOGGER</a> | The logger should have all these methods: `'info'`, `'error'`, `'debug'`, `'fatal'`, `'warn'`, `'trace'`, `'child'`. | Use a logger with all the required methods. | [#4520](https://github.com/fastify/fastify/pull/4520) |
|
|
255
315
|
| <a id="fst_err_rep_invalid_payload_type">FST_ERR_REP_INVALID_PAYLOAD_TYPE</a> | Reply payload can be either a `string` or a `Buffer`. | Use a `string` or a `Buffer` for the payload. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
|
316
|
+
| <a id="fst_err_rep_response_body_consumed">FST_ERR_REP_RESPONSE_BODY_CONSUMED</a> | Using `Response` as reply payload
|
|
317
|
+
but the body is being consumed. | Make sure you don't consume the `Response.body` | [#5286](https://github.com/fastify/fastify/pull/5286) |
|
|
256
318
|
| <a id="fst_err_rep_already_sent">FST_ERR_REP_ALREADY_SENT</a> | A response was already sent. | - | [#1336](https://github.com/fastify/fastify/pull/1336) |
|
|
257
319
|
| <a id="fst_err_rep_sent_value">FST_ERR_REP_SENT_VALUE</a> | The only possible value for `reply.sent` is `true`. | - | [#1336](https://github.com/fastify/fastify/pull/1336) |
|
|
258
320
|
| <a id="fst_err_send_inside_onerr">FST_ERR_SEND_INSIDE_ONERR</a> | You cannot use `send` inside the `onError` hook. | - | [#1348](https://github.com/fastify/fastify/pull/1348) |
|
package/docs/Reference/Hooks.md
CHANGED
|
@@ -232,7 +232,7 @@ fastify.addHook('onSend', (request, reply, payload, done) => {
|
|
|
232
232
|
> `null`.
|
|
233
233
|
|
|
234
234
|
Note: If you change the payload, you may only change it to a `string`, a
|
|
235
|
-
`Buffer`, a `stream`, or `null`.
|
|
235
|
+
`Buffer`, a `stream`, a `ReadableStream`, a `Response`, or `null`.
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
### onResponse
|
|
@@ -61,9 +61,9 @@ the Fastify instance:
|
|
|
61
61
|
fastify.log.info('Something important happened!');
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
If you want to pass some options to the logger, just pass them to Fastify.
|
|
65
|
-
can find all available options in the
|
|
66
|
-
documentation](https://github.com/pinojs/pino/blob/master/docs/api.md#
|
|
64
|
+
If you want to pass some options to the logger, just pass them to Fastify.
|
|
65
|
+
You can find all available options in the
|
|
66
|
+
[Pino documentation](https://github.com/pinojs/pino/blob/master/docs/api.md#options).
|
|
67
67
|
If you want to specify a file destination, use:
|
|
68
68
|
|
|
69
69
|
```js
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
- [Reply](#reply)
|
|
5
5
|
- [Introduction](#introduction)
|
|
6
6
|
- [.code(statusCode)](#codestatuscode)
|
|
7
|
+
- [.elapsedTime](#elapsedtime)
|
|
7
8
|
- [.statusCode](#statuscode)
|
|
8
9
|
- [.server](#server)
|
|
9
10
|
- [.header(key, value)](#headerkey-value)
|
|
@@ -32,6 +33,8 @@
|
|
|
32
33
|
- [Strings](#strings)
|
|
33
34
|
- [Streams](#streams)
|
|
34
35
|
- [Buffers](#buffers)
|
|
36
|
+
- [ReadableStream](#send-readablestream)
|
|
37
|
+
- [Response](#send-response)
|
|
35
38
|
- [Errors](#errors)
|
|
36
39
|
- [Type of the final payload](#type-of-the-final-payload)
|
|
37
40
|
- [Async-Await and Promises](#async-await-and-promises)
|
|
@@ -46,6 +49,8 @@ object that exposes the following functions and properties:
|
|
|
46
49
|
- `.code(statusCode)` - Sets the status code.
|
|
47
50
|
- `.status(statusCode)` - An alias for `.code(statusCode)`.
|
|
48
51
|
- `.statusCode` - Read and set the HTTP status code.
|
|
52
|
+
- `.elapsedTime` - Returns the amount of time passed
|
|
53
|
+
since the request was received by Fastify.
|
|
49
54
|
- `.server` - A reference to the fastify instance object.
|
|
50
55
|
- `.header(name, value)` - Sets a response header.
|
|
51
56
|
- `.headers(object)` - Sets all the keys of the object as response headers.
|
|
@@ -85,6 +90,8 @@ object that exposes the following functions and properties:
|
|
|
85
90
|
from Node core.
|
|
86
91
|
- `.log` - The logger instance of the incoming request.
|
|
87
92
|
- `.request` - The incoming request.
|
|
93
|
+
- `.getResponseTime()` - Deprecated, returns the amount of time passed
|
|
94
|
+
since the request was received by Fastify.
|
|
88
95
|
- `.context` - Deprecated, access the [Request's context](./Request.md) property.
|
|
89
96
|
|
|
90
97
|
```js
|
|
@@ -110,6 +117,19 @@ fastify.get('/', {config: {foo: 'bar'}}, function (request, reply) {
|
|
|
110
117
|
|
|
111
118
|
If not set via `reply.code`, the resulting `statusCode` will be `200`.
|
|
112
119
|
|
|
120
|
+
### .elapsedTime
|
|
121
|
+
<a id="elapsedTime"></a>
|
|
122
|
+
|
|
123
|
+
Invokes the custom response time getter to calculate the amount of time passed
|
|
124
|
+
since the request was received by Fastify.
|
|
125
|
+
|
|
126
|
+
Note that unless this function is called in the [`onResponse`
|
|
127
|
+
hook](./Hooks.md#onresponse) it will always return `0`.
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
const milliseconds = reply.elapsedTime
|
|
131
|
+
```
|
|
132
|
+
|
|
113
133
|
### .statusCode
|
|
114
134
|
<a id="statusCode"></a>
|
|
115
135
|
|
|
@@ -327,7 +347,7 @@ reply.callNotFound()
|
|
|
327
347
|
<a id="getResponseTime"></a>
|
|
328
348
|
|
|
329
349
|
Invokes the custom response time getter to calculate the amount of time passed
|
|
330
|
-
since the request was
|
|
350
|
+
since the request was received by Fastify.
|
|
331
351
|
|
|
332
352
|
Note that unless this function is called in the [`onResponse`
|
|
333
353
|
hook](./Hooks.md#onresponse) it will always return `0`.
|
|
@@ -336,6 +356,9 @@ hook](./Hooks.md#onresponse) it will always return `0`.
|
|
|
336
356
|
const milliseconds = reply.getResponseTime()
|
|
337
357
|
```
|
|
338
358
|
|
|
359
|
+
*Note: This method is deprecated and will be removed in `fastify@5`.
|
|
360
|
+
Use the [.elapsedTime](#elapsedtime) property instead.*
|
|
361
|
+
|
|
339
362
|
### .type(contentType)
|
|
340
363
|
<a id="type"></a>
|
|
341
364
|
|
|
@@ -735,6 +758,52 @@ fastify.get('/streams', function (request, reply) {
|
|
|
735
758
|
})
|
|
736
759
|
```
|
|
737
760
|
|
|
761
|
+
#### ReadableStream
|
|
762
|
+
<a id="send-readablestream"></a>
|
|
763
|
+
|
|
764
|
+
`ReadableStream` will be treated as a node stream mentioned above,
|
|
765
|
+
the content is considered to be pre-serialized, so they will be
|
|
766
|
+
sent unmodified without response validation.
|
|
767
|
+
|
|
768
|
+
```js
|
|
769
|
+
const fs = require('node:fs')
|
|
770
|
+
const { ReadableStream } = require('node:stream/web')
|
|
771
|
+
fastify.get('/streams', function (request, reply) {
|
|
772
|
+
const stream = fs.createReadStream('some-file')
|
|
773
|
+
reply.header('Content-Type', 'application/octet-stream')
|
|
774
|
+
reply.send(ReadableStream.from(stream))
|
|
775
|
+
})
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
#### Response
|
|
779
|
+
<a id="send-response"></a>
|
|
780
|
+
|
|
781
|
+
`Response` allows to manage the reply payload, status code and
|
|
782
|
+
headers in one place. The payload provided inside `Response` is
|
|
783
|
+
considered to be pre-serialized, so they will be sent unmodified
|
|
784
|
+
without response validation.
|
|
785
|
+
|
|
786
|
+
Plese be aware when using `Response`, the status code and headers
|
|
787
|
+
will not directly reflect to `reply.statusCode` and `reply.getHeaders()`.
|
|
788
|
+
Such behavior is based on `Response` only allow `readonly` status
|
|
789
|
+
code and headers. The data is not allow to be bi-direction editing,
|
|
790
|
+
and may confuse when checking the `payload` in `onSend` hooks.
|
|
791
|
+
|
|
792
|
+
```js
|
|
793
|
+
const fs = require('node:fs')
|
|
794
|
+
const { ReadableStream } = require('node:stream/web')
|
|
795
|
+
fastify.get('/streams', function (request, reply) {
|
|
796
|
+
const stream = fs.createReadStream('some-file')
|
|
797
|
+
const readableStream = ReadableStream.from(stream)
|
|
798
|
+
const response = new Response(readableStream, {
|
|
799
|
+
status: 200,
|
|
800
|
+
headers: { 'content-type': 'application/octet-stream' }
|
|
801
|
+
})
|
|
802
|
+
reply.send(response)
|
|
803
|
+
})
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
|
|
738
807
|
#### Errors
|
|
739
808
|
<a id="errors"></a>
|
|
740
809
|
|
package/docs/Reference/Server.md
CHANGED
|
@@ -44,6 +44,7 @@ describes the properties available in that options object.
|
|
|
44
44
|
- [`frameworkErrors`](#frameworkerrors)
|
|
45
45
|
- [`clientErrorHandler`](#clienterrorhandler)
|
|
46
46
|
- [`rewriteUrl`](#rewriteurl)
|
|
47
|
+
- [`useSemicolonDelimiter`](#usesemicolondelimiter)
|
|
47
48
|
- [Instance](#instance)
|
|
48
49
|
- [Server Methods](#server-methods)
|
|
49
50
|
- [server](#server)
|
|
@@ -57,6 +58,7 @@ describes the properties available in that options object.
|
|
|
57
58
|
- [routing](#routing)
|
|
58
59
|
- [route](#route)
|
|
59
60
|
- [hasRoute](#hasroute)
|
|
61
|
+
- [findRoute](#findroute)
|
|
60
62
|
- [close](#close)
|
|
61
63
|
- [decorate\*](#decorate)
|
|
62
64
|
- [register](#register)
|
|
@@ -82,6 +84,7 @@ describes the properties available in that options object.
|
|
|
82
84
|
- [setNotFoundHandler](#setnotfoundhandler)
|
|
83
85
|
- [setErrorHandler](#seterrorhandler)
|
|
84
86
|
- [setChildLoggerFactory](#setchildloggerfactory)
|
|
87
|
+
- [setGenReqId](#setGenReqId)
|
|
85
88
|
- [addConstraintStrategy](#addconstraintstrategy)
|
|
86
89
|
- [hasConstraintStrategy](#hasconstraintstrategy)
|
|
87
90
|
- [printRoutes](#printroutes)
|
|
@@ -859,6 +862,31 @@ function rewriteUrl (req) {
|
|
|
859
862
|
}
|
|
860
863
|
```
|
|
861
864
|
|
|
865
|
+
### `useSemicolonDelimiter`
|
|
866
|
+
<a id="use-semicolon-delimiter"></a>
|
|
867
|
+
|
|
868
|
+
+ Default `true`
|
|
869
|
+
|
|
870
|
+
Fastify uses [find-my-way](https://github.com/delvedor/find-my-way) which supports,
|
|
871
|
+
separating the path and query string with a `;` character (code 59), e.g. `/dev;foo=bar`.
|
|
872
|
+
This decision originated from [delvedor/find-my-way#76]
|
|
873
|
+
(https://github.com/delvedor/find-my-way/issues/76). Thus, this option will support
|
|
874
|
+
backwards compatiblilty for the need to split on `;`. To disable support for splitting
|
|
875
|
+
on `;` set `useSemicolonDelimiter` to `false`.
|
|
876
|
+
|
|
877
|
+
```js
|
|
878
|
+
const fastify = require('fastify')({
|
|
879
|
+
useSemicolonDelimiter: true
|
|
880
|
+
})
|
|
881
|
+
|
|
882
|
+
fastify.get('/dev', async (request, reply) => {
|
|
883
|
+
// An example request such as `/dev;foo=bar`
|
|
884
|
+
// Will produce the following query params result `{ foo = 'bar' }`
|
|
885
|
+
return request.query
|
|
886
|
+
})
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
|
|
862
890
|
## Instance
|
|
863
891
|
|
|
864
892
|
### Server Methods
|
|
@@ -1148,6 +1176,28 @@ if (routeExists === false) {
|
|
|
1148
1176
|
}
|
|
1149
1177
|
```
|
|
1150
1178
|
|
|
1179
|
+
#### findRoute
|
|
1180
|
+
<a id="findRoute"></a>
|
|
1181
|
+
|
|
1182
|
+
Method to retrieve a route already registered to the internal router. It
|
|
1183
|
+
expects an object as the payload. `url` and `method` are mandatory fields. It
|
|
1184
|
+
is possible to also specify `constraints`.
|
|
1185
|
+
The method returns a route object or `null` if the route cannot be found.
|
|
1186
|
+
|
|
1187
|
+
```js
|
|
1188
|
+
const route = fastify.findRoute({
|
|
1189
|
+
url: '/artists/:artistId',
|
|
1190
|
+
method: 'GET',
|
|
1191
|
+
constraints: { version: '1.0.0' } // optional
|
|
1192
|
+
})
|
|
1193
|
+
|
|
1194
|
+
if (route !== null) {
|
|
1195
|
+
// perform some route checks
|
|
1196
|
+
console.log(route.params) // `{artistId: ':artistId'}`
|
|
1197
|
+
}
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
|
|
1151
1201
|
#### close
|
|
1152
1202
|
<a id="close"></a>
|
|
1153
1203
|
|
|
@@ -1591,6 +1641,45 @@ const fastify = require('fastify')({
|
|
|
1591
1641
|
The handler is bound to the Fastify instance and is fully encapsulated, so
|
|
1592
1642
|
different plugins can set different logger factories.
|
|
1593
1643
|
|
|
1644
|
+
#### setGenReqId
|
|
1645
|
+
<a id="set-gen-req-id"></a>
|
|
1646
|
+
|
|
1647
|
+
`fastify.setGenReqId(function (rawReq))` Synchronous function for setting the request-id
|
|
1648
|
+
for additional Fastify instances. It will receive the _raw_ incoming request as a
|
|
1649
|
+
parameter. The provided function should not throw an Error in any case.
|
|
1650
|
+
|
|
1651
|
+
Especially in distributed systems, you may want to override the default ID
|
|
1652
|
+
generation behavior to handle custom ways of generating different IDs in
|
|
1653
|
+
order to handle different use cases. Such as observability or webhooks plugins.
|
|
1654
|
+
|
|
1655
|
+
For example:
|
|
1656
|
+
```js
|
|
1657
|
+
const fastify = require('fastify')({
|
|
1658
|
+
genReqId: (req) => {
|
|
1659
|
+
return 'base'
|
|
1660
|
+
}
|
|
1661
|
+
})
|
|
1662
|
+
|
|
1663
|
+
fastify.register((instance, opts, done) => {
|
|
1664
|
+
instance.setGenReqId((req) => {
|
|
1665
|
+
// custom request ID for `/webhooks`
|
|
1666
|
+
return 'webhooks-id'
|
|
1667
|
+
})
|
|
1668
|
+
done()
|
|
1669
|
+
}, { prefix: '/webhooks' })
|
|
1670
|
+
|
|
1671
|
+
fastify.register((instance, opts, done) => {
|
|
1672
|
+
instance.setGenReqId((req) => {
|
|
1673
|
+
// custom request ID for `/observability`
|
|
1674
|
+
return 'observability-id'
|
|
1675
|
+
})
|
|
1676
|
+
done()
|
|
1677
|
+
}, { prefix: '/observability' })
|
|
1678
|
+
```
|
|
1679
|
+
|
|
1680
|
+
The handler is bound to the Fastify instance and is fully encapsulated, so
|
|
1681
|
+
different plugins can set a different request ID.
|
|
1682
|
+
|
|
1594
1683
|
#### addConstraintStrategy
|
|
1595
1684
|
<a id="addConstraintStrategy"></a>
|
|
1596
1685
|
|
|
@@ -1920,6 +2009,7 @@ The properties that can currently be exposed are:
|
|
|
1920
2009
|
- requestIdHeader
|
|
1921
2010
|
- requestIdLogLabel
|
|
1922
2011
|
- http2SessionTimeout
|
|
2012
|
+
- useSemicolonDelimiter
|
|
1923
2013
|
|
|
1924
2014
|
```js
|
|
1925
2015
|
const { readFileSync } = require('node:fs')
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
- [FSTDEP017](#FSTDEP017)
|
|
24
24
|
- [FSTDEP018](#FSTDEP018)
|
|
25
25
|
- [FSTDEP019](#FSTDEP019)
|
|
26
|
+
- [FSTDEP020](#FSTDEP020)
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
## Warnings
|
|
@@ -75,3 +76,4 @@ Deprecation codes are further supported by the Node.js CLI options:
|
|
|
75
76
|
| <a id="FSTDEP017">FSTDEP017</a> | You are accessing the deprecated `request.routerPath` property. | Use `request.routeOptions.url`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
|
|
76
77
|
| <a id="FSTDEP018">FSTDEP018</a> | You are accessing the deprecated `request.routerMethod` property. | Use `request.routeOptions.method`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
|
|
77
78
|
| <a id="FSTDEP019">FSTDEP019</a> | You are accessing the deprecated `reply.context` property. | Use `reply.routeOptions.config` or `reply.routeOptions.schema`. | [#5032](https://github.com/fastify/fastify/pull/5032) [#5084](https://github.com/fastify/fastify/pull/5084) |
|
|
79
|
+
| <a id="FSTDEP020">FSTDEP020</a> | You are using the deprecated `reply.getReponseTime()` method. | Use the `reply.elapsedTime` property instead. | [#5263](https://github.com/fastify/fastify/pull/5263) |
|
package/fastify.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { FastifyRequestContext, FastifyContextConfig, FastifyReplyContext } from
|
|
|
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'
|
|
17
|
-
import { FastifyBaseLogger, FastifyLoggerInstance, FastifyLoggerOptions, PinoLoggerOptions, FastifyLogFn, LogLevel
|
|
17
|
+
import { FastifyBaseLogger, FastifyLoggerInstance, FastifyLoggerOptions, PinoLoggerOptions, FastifyLogFn, LogLevel } from './types/logger'
|
|
18
18
|
import { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin } from './types/plugin'
|
|
19
19
|
import { FastifyRegister, FastifyRegisterOptions, RegisterOptions } from './types/register'
|
|
20
20
|
import { FastifyReply } from './types/reply'
|
|
@@ -109,6 +109,7 @@ declare namespace fastify {
|
|
|
109
109
|
allowUnsafeRegex?: boolean,
|
|
110
110
|
requestIdHeader?: string | false,
|
|
111
111
|
requestIdLogLabel?: string;
|
|
112
|
+
useSemicolonDelimiter?: boolean,
|
|
112
113
|
jsonShorthand?: boolean;
|
|
113
114
|
genReqId?: (req: RawRequestDefaultExpression<RawServer>) => string,
|
|
114
115
|
trustProxy?: boolean | string | string[] | number | TrustProxyFunction,
|
|
@@ -238,4 +239,4 @@ declare function fastify<
|
|
|
238
239
|
|
|
239
240
|
// CJS export
|
|
240
241
|
// const fastify = require('fastify')
|
|
241
|
-
export = fastify
|
|
242
|
+
export = fastify
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.26.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('node:http')
|
|
@@ -28,7 +28,8 @@ const {
|
|
|
28
28
|
kSchemaErrorFormatter,
|
|
29
29
|
kErrorHandler,
|
|
30
30
|
kKeepAliveConnections,
|
|
31
|
-
kChildLoggerFactory
|
|
31
|
+
kChildLoggerFactory,
|
|
32
|
+
kGenReqId
|
|
32
33
|
} = require('./lib/symbols.js')
|
|
33
34
|
|
|
34
35
|
const { createServer, compileValidateHTTPVersion } = require('./lib/server')
|
|
@@ -42,7 +43,7 @@ const SchemaController = require('./lib/schema-controller')
|
|
|
42
43
|
const { Hooks, hookRunnerApplication, supportedHooks } = require('./lib/hooks')
|
|
43
44
|
const { createLogger, createChildLogger, defaultChildLoggerFactory } = require('./lib/logger')
|
|
44
45
|
const pluginUtils = require('./lib/pluginUtils')
|
|
45
|
-
const { reqIdGenFactory } = require('./lib/reqIdGenFactory')
|
|
46
|
+
const { getGenReqId, reqIdGenFactory } = require('./lib/reqIdGenFactory')
|
|
46
47
|
const { buildRouting, validateBodyLimitOption } = require('./lib/route')
|
|
47
48
|
const build404 = require('./lib/fourOhFour')
|
|
48
49
|
const getSecuredInitialConfig = require('./lib/initialConfigValidation')
|
|
@@ -138,7 +139,6 @@ function fastify (options) {
|
|
|
138
139
|
options.maxRequestsPerSocket = options.maxRequestsPerSocket || defaultInitOptions.maxRequestsPerSocket
|
|
139
140
|
options.requestTimeout = options.requestTimeout || defaultInitOptions.requestTimeout
|
|
140
141
|
options.logger = logger
|
|
141
|
-
options.genReqId = genReqId
|
|
142
142
|
options.requestIdHeader = requestIdHeader
|
|
143
143
|
options.requestIdLogLabel = requestIdLogLabel
|
|
144
144
|
options.disableRequestLogging = disableRequestLogging
|
|
@@ -181,7 +181,8 @@ function fastify (options) {
|
|
|
181
181
|
caseSensitive: options.caseSensitive,
|
|
182
182
|
allowUnsafeRegex: options.allowUnsafeRegex || defaultInitOptions.allowUnsafeRegex,
|
|
183
183
|
buildPrettyMeta: defaultBuildPrettyMeta,
|
|
184
|
-
querystringParser: options.querystringParser
|
|
184
|
+
querystringParser: options.querystringParser,
|
|
185
|
+
useSemicolonDelimiter: options.useSemicolonDelimiter ?? defaultInitOptions.useSemicolonDelimiter
|
|
185
186
|
}
|
|
186
187
|
})
|
|
187
188
|
|
|
@@ -247,6 +248,7 @@ function fastify (options) {
|
|
|
247
248
|
[pluginUtils.kRegisteredPlugins]: [],
|
|
248
249
|
[kPluginNameChain]: ['fastify'],
|
|
249
250
|
[kAvvioBoot]: null,
|
|
251
|
+
[kGenReqId]: genReqId,
|
|
250
252
|
// routing method
|
|
251
253
|
routing: httpHandler,
|
|
252
254
|
getDefaultRoute: router.getDefaultRoute.bind(router),
|
|
@@ -285,6 +287,9 @@ function fastify (options) {
|
|
|
285
287
|
hasRoute: function _route (options) {
|
|
286
288
|
return router.hasRoute.call(this, { options })
|
|
287
289
|
},
|
|
290
|
+
findRoute: function _findRoute (options) {
|
|
291
|
+
return router.findRoute(options)
|
|
292
|
+
},
|
|
288
293
|
// expose logger instance
|
|
289
294
|
log: logger,
|
|
290
295
|
// type provider
|
|
@@ -300,6 +305,8 @@ function fastify (options) {
|
|
|
300
305
|
setSchemaController,
|
|
301
306
|
setReplySerializer,
|
|
302
307
|
setSchemaErrorFormatter,
|
|
308
|
+
// set generated request id
|
|
309
|
+
setGenReqId,
|
|
303
310
|
// custom parsers
|
|
304
311
|
addContentTypeParser: ContentTypeParser.helpers.addContentTypeParser,
|
|
305
312
|
hasContentTypeParser: ContentTypeParser.helpers.hasContentTypeParser,
|
|
@@ -396,6 +403,10 @@ function fastify (options) {
|
|
|
396
403
|
get () {
|
|
397
404
|
return this[kErrorHandler].func
|
|
398
405
|
}
|
|
406
|
+
},
|
|
407
|
+
genReqId: {
|
|
408
|
+
configurable: true,
|
|
409
|
+
get () { return this[kGenReqId] }
|
|
399
410
|
}
|
|
400
411
|
})
|
|
401
412
|
|
|
@@ -739,7 +750,7 @@ function fastify (options) {
|
|
|
739
750
|
|
|
740
751
|
function onBadUrl (path, req, res) {
|
|
741
752
|
if (frameworkErrors) {
|
|
742
|
-
const id =
|
|
753
|
+
const id = getGenReqId(onBadUrlContext.server, req)
|
|
743
754
|
const childLogger = createChildLogger(onBadUrlContext, logger, req, id)
|
|
744
755
|
|
|
745
756
|
const request = new Request(id, null, req, null, childLogger, onBadUrlContext)
|
|
@@ -764,7 +775,7 @@ function fastify (options) {
|
|
|
764
775
|
return function onAsyncConstraintError (err) {
|
|
765
776
|
if (err) {
|
|
766
777
|
if (frameworkErrors) {
|
|
767
|
-
const id =
|
|
778
|
+
const id = getGenReqId(onBadUrlContext.server, req)
|
|
768
779
|
const childLogger = createChildLogger(onBadUrlContext, logger, req, id)
|
|
769
780
|
|
|
770
781
|
const request = new Request(id, null, req, null, childLogger, onBadUrlContext)
|
|
@@ -868,6 +879,13 @@ function fastify (options) {
|
|
|
868
879
|
router.routing(req, res, buildAsyncConstraintCallback(isAsync, req, res))
|
|
869
880
|
}
|
|
870
881
|
}
|
|
882
|
+
|
|
883
|
+
function setGenReqId (func) {
|
|
884
|
+
throwIfAlreadyStarted('Cannot call "setGenReqId"!')
|
|
885
|
+
|
|
886
|
+
this[kGenReqId] = reqIdGenFactory(this[kOptions].requestIdHeader, func)
|
|
887
|
+
return this
|
|
888
|
+
}
|
|
871
889
|
}
|
|
872
890
|
|
|
873
891
|
fastify.errorCodes = errorCodes
|