fastify 3.9.2 → 3.12.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/GOVERNANCE.md +1 -1
- package/README.md +12 -8
- package/SECURITY.md +3 -3
- package/docs/ContentTypeParser.md +1 -1
- package/docs/Ecosystem.md +16 -6
- package/docs/Encapsulation.md +5 -2
- package/docs/Fluent-Schema.md +4 -4
- package/docs/Getting-Started.md +1 -1
- package/docs/Hooks.md +28 -1
- package/docs/Lifecycle.md +8 -1
- package/docs/Middleware.md +5 -4
- package/docs/Reply.md +13 -4
- package/docs/Routes.md +4 -3
- package/docs/Server.md +78 -4
- package/docs/Serverless.md +23 -51
- package/docs/TypeScript.md +35 -18
- package/docs/Validation-and-Serialization.md +4 -4
- package/docs/Write-Plugin.md +4 -4
- package/examples/hooks-benchmark.js +12 -12
- package/examples/hooks.js +16 -16
- package/examples/plugin.js +2 -2
- package/examples/route-prefix.js +4 -4
- package/fastify.d.ts +16 -1
- package/fastify.js +33 -16
- package/isolate-0x426d1e0-1227-v8.log +4019 -0
- package/isolate-0x4d4c7e0-1988-v8.log +4081 -0
- package/lib/errors.js +6 -0
- package/lib/headRoute.js +31 -0
- package/lib/pluginOverride.js +5 -5
- package/lib/pluginUtils.js +7 -6
- package/lib/reply.js +14 -2
- package/lib/reqIdGenFactory.js +5 -0
- package/lib/request.js +1 -1
- package/lib/route.js +66 -41
- package/lib/schema-compilers.js +5 -3
- package/lib/schema-controller.js +106 -0
- package/lib/schemas.js +14 -24
- package/lib/server.js +1 -0
- package/lib/symbols.js +1 -3
- package/lib/warnings.js +2 -0
- package/lib/wrapThenable.js +2 -1
- package/package.json +25 -21
- package/test/404s.test.js +120 -120
- package/test/500s.test.js +8 -8
- package/test/async-await.test.js +29 -1
- package/test/close.test.js +8 -8
- package/test/context-config.test.js +52 -0
- package/test/custom-parser.test.js +8 -8
- package/test/decorator.test.js +49 -49
- package/test/default-route.test.js +43 -0
- package/test/fastify-instance.test.js +2 -2
- package/test/fluent-schema.test.js +3 -3
- package/test/handler-context.test.js +2 -2
- package/test/hooks-async.test.js +3 -3
- package/test/hooks.on-ready.test.js +12 -12
- package/test/hooks.test.js +75 -32
- package/test/http2/closing.test.js +23 -1
- package/test/inject.test.js +6 -6
- package/test/input-validation.js +2 -2
- package/test/internals/hookRunner.test.js +50 -50
- package/test/internals/reply.test.js +47 -22
- package/test/internals/request.test.js +3 -9
- package/test/internals/version.test.js +2 -2
- package/test/logger.test.js +30 -30
- package/test/middleware.test.js +4 -4
- package/test/plugin.helper.js +2 -2
- package/test/plugin.test.js +154 -99
- package/test/register.test.js +11 -11
- package/test/request-error.test.js +2 -2
- package/test/route-hooks.test.js +24 -24
- package/test/route-prefix.test.js +81 -52
- package/test/route.test.js +568 -0
- package/test/schema-feature.test.js +168 -38
- package/test/schema-serialization.test.js +4 -4
- package/test/schema-special-usage.test.js +136 -0
- package/test/schema-validation.test.js +7 -7
- package/test/skip-reply-send.test.js +315 -0
- package/test/stream.test.js +6 -6
- package/test/throw.test.js +4 -4
- package/test/types/instance.test-d.ts +5 -3
- package/test/types/plugin.test-d.ts +7 -7
- package/test/types/reply.test-d.ts +1 -0
- package/test/types/schema.test-d.ts +15 -0
- package/test/validation-error-handling.test.js +5 -5
- package/test/versioned-routes.test.js +1 -1
- package/types/content-type-parser.d.ts +1 -1
- package/types/instance.d.ts +6 -3
- package/types/plugin.d.ts +1 -1
- package/types/reply.d.ts +1 -0
- package/types/route.d.ts +8 -2
- package/types/schema.d.ts +3 -0
- package/test/skip-reply-send.js +0 -98
package/docs/Server.md
CHANGED
|
@@ -133,8 +133,6 @@ logger will point to this instance.
|
|
|
133
133
|
+ `object`: a standard Pino [options object](https://github.com/pinojs/pino/blob/c77d8ec5ce/docs/API.md#constructor).
|
|
134
134
|
This will be passed directly to the Pino constructor. If the following properties
|
|
135
135
|
are not present on the object, they will be added accordingly:
|
|
136
|
-
* `genReqId`: a synchronous function that will be used to generate identifiers
|
|
137
|
-
for incoming requests. The default function generates sequential identifiers.
|
|
138
136
|
* `level`: the minimum logging level. If not set, it will be set to `'info'`.
|
|
139
137
|
* `serializers`: a hash of serialization functions. By default, serializers
|
|
140
138
|
are added for `req` (incoming request objects), `res` (outgoing response
|
|
@@ -328,6 +326,13 @@ const fastify = require('fastify')({
|
|
|
328
326
|
})
|
|
329
327
|
```
|
|
330
328
|
|
|
329
|
+
<a name="exposeHeadRoutes"></a>
|
|
330
|
+
### `exposeHeadRoutes`
|
|
331
|
+
|
|
332
|
+
Automatically creates a sibling `HEAD` route for each `GET` route defined. If you want a custom `HEAD` handler without disabling this option, make sure to define it before the `GET` route.
|
|
333
|
+
|
|
334
|
+
+ Default: `false`
|
|
335
|
+
|
|
331
336
|
<a name="versioning"></a>
|
|
332
337
|
### `versioning`
|
|
333
338
|
|
|
@@ -457,7 +462,7 @@ function defaultClientErrorHandler (err, socket) {
|
|
|
457
462
|
}
|
|
458
463
|
```
|
|
459
464
|
|
|
460
|
-
*Note: `clientErrorHandler` operates with raw socket. The handler is expected to return a properly formed HTTP response that includes a status line, HTTP headers and a message body. Before attempting to write the socket, the handler should check if the socket
|
|
465
|
+
*Note: `clientErrorHandler` operates with raw socket. The handler is expected to return a properly formed HTTP response that includes a status line, HTTP headers and a message body. Before attempting to write the socket, the handler should check if the socket is still writable as it may have already been destroyed.*
|
|
461
466
|
|
|
462
467
|
```js
|
|
463
468
|
const fastify = require('fastify')({
|
|
@@ -668,6 +673,34 @@ fastify.listen({
|
|
|
668
673
|
}, (err) => {})
|
|
669
674
|
```
|
|
670
675
|
|
|
676
|
+
<a name="getDefaultRoute"></a>
|
|
677
|
+
#### getDefaultRoute
|
|
678
|
+
Method to get the `defaultRoute` for the server:
|
|
679
|
+
|
|
680
|
+
```js
|
|
681
|
+
const defaultRoute = fastify.getDefaultRoute()
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
<a name="setDefaultRoute"></a>
|
|
685
|
+
#### setDefaultRoute
|
|
686
|
+
Method to set the `defaultRoute` for the server:
|
|
687
|
+
|
|
688
|
+
```js
|
|
689
|
+
const defaultRoute = function (req, res) {
|
|
690
|
+
res.end('hello world')
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
fastify.setDefaultRoute(defaultRoute)
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
<a name="routing"></a>
|
|
697
|
+
#### routing
|
|
698
|
+
Method to access the `lookup` method of the internal router and match the request to the appropriate handler:
|
|
699
|
+
|
|
700
|
+
```js
|
|
701
|
+
fastify.routing(req, res)
|
|
702
|
+
```
|
|
703
|
+
|
|
671
704
|
<a name="route"></a>
|
|
672
705
|
#### route
|
|
673
706
|
Method to add routes to the server, it also has shorthand functions, check [here](Routes.md).
|
|
@@ -737,7 +770,7 @@ Name of the current plugin. There are three ways to define a name (in order).
|
|
|
737
770
|
2. If you `module.exports` a plugin the filename is used.
|
|
738
771
|
3. If you use a regular [function declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#Defining_functions) the function name is used.
|
|
739
772
|
|
|
740
|
-
*Fallback*: The first two lines of your plugin will represent the plugin name. Newlines are replaced by ` -- `. This will help to
|
|
773
|
+
*Fallback*: The first two lines of your plugin will represent the plugin name. Newlines are replaced by ` -- `. This will help to identify the root cause when you deal with many plugins.
|
|
741
774
|
|
|
742
775
|
Important: If you have to deal with nested plugins the name differs with the usage of the [fastify-plugin](https://github.com/fastify/fastify-plugin) because no new scope is created and therefore we have no place to attach contextual data. In that case the plugin name will represent the boot order of all involved plugins in the format of `plugin-A -> plugin-B`.
|
|
743
776
|
|
|
@@ -805,6 +838,47 @@ The input `schema` can access all the shared schemas added with [`.addSchema`](#
|
|
|
805
838
|
#### schemaErrorFormatter
|
|
806
839
|
This property can be used set a function to format errors that happen while the `validationCompiler` fails to validate the schema. See [#error-handling](Validation-and-Serialization.md#schemaerrorformatter).
|
|
807
840
|
|
|
841
|
+
<a name="schema-controller"></a>
|
|
842
|
+
#### schemaController
|
|
843
|
+
This property can be used to fully manage where the schemas of your application will be stored.
|
|
844
|
+
It can be useful when your schemas are stored in another data structure that is unknown to Fastify.
|
|
845
|
+
See [issue #2446](https://github.com/fastify/fastify/issues/2446) for an example of what
|
|
846
|
+
this property helps to resolve.
|
|
847
|
+
|
|
848
|
+
```js
|
|
849
|
+
const fastify = Fastify({
|
|
850
|
+
schemaController: {
|
|
851
|
+
/**
|
|
852
|
+
* This factory is called whenever `fastify.register()` is called.
|
|
853
|
+
* It may receive as input the schemas of the parent context if some schemas has been added.
|
|
854
|
+
* @param {object} parentSchemas these schemas will be returned by the `getSchemas()` method function of the returned `bucket`.
|
|
855
|
+
*/
|
|
856
|
+
bucket: function factory (parentSchemas) {
|
|
857
|
+
return {
|
|
858
|
+
addSchema (inputSchema) {
|
|
859
|
+
// This function must store the schema added by the user.
|
|
860
|
+
// This function is invoked when `fastify.addSchema()` is called.
|
|
861
|
+
},
|
|
862
|
+
getSchema (schema$id) {
|
|
863
|
+
// This function must return the raw schema requested by the `schema$id`.
|
|
864
|
+
// This function is invoked when `fastify.getSchema(id)` is called.
|
|
865
|
+
return aSchema
|
|
866
|
+
},
|
|
867
|
+
getSchemas () {
|
|
868
|
+
// This function must return all the schemas referenced by the routes schemas' $ref
|
|
869
|
+
// It must return a JSON where the property is the schema `$id` and the value is the raw JSON Schema.
|
|
870
|
+
const allTheSchemaStored = {
|
|
871
|
+
'schema$id1': schema1,
|
|
872
|
+
'schema$id2': schema2
|
|
873
|
+
}
|
|
874
|
+
return allTheSchemaStored
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
```
|
|
881
|
+
|
|
808
882
|
<a name="set-not-found-handler"></a>
|
|
809
883
|
#### setNotFoundHandler
|
|
810
884
|
|
package/docs/Serverless.md
CHANGED
|
@@ -99,7 +99,7 @@ Unlike AWS Lambda or Google Cloud Functions, Google Cloud Run is a serverless **
|
|
|
99
99
|
|
|
100
100
|
*Follow the steps below to deploy to Google Cloud Run if you are already familiar with gcloud or just follow their [quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy)*.
|
|
101
101
|
|
|
102
|
-
### Adjust
|
|
102
|
+
### Adjust Fastify server
|
|
103
103
|
|
|
104
104
|
In order for Fastify to properly listen for requests within the container, be sure to set the correct port and address:
|
|
105
105
|
|
|
@@ -279,69 +279,41 @@ Then it should work fine
|
|
|
279
279
|
|
|
280
280
|
[Vercel](https://vercel.com) provides zero configuration deployment for
|
|
281
281
|
Node.js applications. In order to use now, it is as simple as
|
|
282
|
-
configuring your `
|
|
282
|
+
configuring your `vercel.json` file like the following:
|
|
283
283
|
|
|
284
284
|
```json
|
|
285
285
|
{
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
"helpers": false
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
],
|
|
296
|
-
"routes": [
|
|
297
|
-
{ "src": "/.*", "dest": "/api/serverless.js"}
|
|
298
|
-
]
|
|
286
|
+
"rewrites": [
|
|
287
|
+
{
|
|
288
|
+
"source": "/(.*)",
|
|
289
|
+
"destination": "/api/serverless.js"
|
|
290
|
+
}
|
|
291
|
+
]
|
|
299
292
|
}
|
|
300
293
|
```
|
|
301
294
|
|
|
302
295
|
Then, write a `api/serverless.js` like so:
|
|
303
296
|
|
|
304
297
|
```js
|
|
305
|
-
|
|
298
|
+
"use strict";
|
|
306
299
|
|
|
307
|
-
|
|
300
|
+
// Read the .env file.
|
|
301
|
+
import * as dotenv from "dotenv";
|
|
302
|
+
dotenv.config();
|
|
308
303
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
module.exports = async function (req, res) {
|
|
312
|
-
await app.ready()
|
|
313
|
-
app.server.emit('request', req, res)
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
And a `api/index.js` file:
|
|
318
|
-
|
|
319
|
-
```js
|
|
320
|
-
'use strict'
|
|
304
|
+
// Require the framework
|
|
305
|
+
import Fastify from "fastify";
|
|
321
306
|
|
|
322
|
-
|
|
307
|
+
// Instantiate Fastify with some config
|
|
308
|
+
const app = Fastify({
|
|
309
|
+
logger: true,
|
|
310
|
+
});
|
|
323
311
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
logger: true
|
|
327
|
-
})
|
|
312
|
+
// Register your application as a normal plugin.
|
|
313
|
+
app.register(import("../src/app"));
|
|
328
314
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return `Hello ${name}!`
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
return app
|
|
315
|
+
export default async (req, res) => {
|
|
316
|
+
await app.ready();
|
|
317
|
+
app.server.emit('request', req, res);
|
|
336
318
|
}
|
|
337
|
-
|
|
338
|
-
module.exports = build
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
Note that you'll need to use Node 10 by setting it in `package.json`:
|
|
342
|
-
|
|
343
|
-
```js
|
|
344
|
-
"engines": {
|
|
345
|
-
"node": "10.x"
|
|
346
|
-
},
|
|
347
319
|
```
|
package/docs/TypeScript.md
CHANGED
|
@@ -10,7 +10,7 @@ The type system was changed in Fastify version 3. The new type system introduces
|
|
|
10
10
|
|
|
11
11
|
> Plugins may or may not include typings. See [Plugins](#plugins) for more information. We encourage users to send pull requests to improve typings support.
|
|
12
12
|
|
|
13
|
-
🚨 Don't
|
|
13
|
+
🚨 Don't forget to install `@types/node`
|
|
14
14
|
|
|
15
15
|
## Learn By Example
|
|
16
16
|
|
|
@@ -37,7 +37,7 @@ This example will get you up and running with Fastify and TypeScript. It results
|
|
|
37
37
|
```
|
|
38
38
|
3. Initialize a TypeScript configuration file:
|
|
39
39
|
```bash
|
|
40
|
-
npx
|
|
40
|
+
npx tsc --init
|
|
41
41
|
```
|
|
42
42
|
or use one of the [recommended ones](https://github.com/tsconfig/bases#node-10-tsconfigjson).
|
|
43
43
|
|
|
@@ -82,7 +82,7 @@ The type system heavily relies on generic properties to provide the most accurat
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
interface IHeaders {
|
|
85
|
-
'
|
|
85
|
+
'h-Custom': string;
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
3. Using the two interfaces, define a new API route and pass them as generics. The shorthand route methods (i.e. `.get`) accept a generic object `RequestGenericInterface` containing four named properties: `Body`, `Querystring`, `Params`, and `Headers`. The interfaces will be passed down through the route method into the route method handler `request` instance.
|
|
@@ -92,7 +92,7 @@ The type system heavily relies on generic properties to provide the most accurat
|
|
|
92
92
|
Headers: IHeaders
|
|
93
93
|
}>('/auth', async (request, reply) => {
|
|
94
94
|
const { username, password } = request.query
|
|
95
|
-
const customerHeader = request.headers['
|
|
95
|
+
const customerHeader = request.headers['h-Custom']
|
|
96
96
|
// do something with request data
|
|
97
97
|
|
|
98
98
|
return `logged in!`
|
|
@@ -115,7 +115,7 @@ The type system heavily relies on generic properties to provide the most accurat
|
|
|
115
115
|
done(username !== 'admin' ? new Error('Must be admin') : undefined) // only validate `admin` account
|
|
116
116
|
}
|
|
117
117
|
}, async (request, reply) => {
|
|
118
|
-
const customerHeader = request.headers['
|
|
118
|
+
const customerHeader = request.headers['h-Custom']
|
|
119
119
|
// do something with request data
|
|
120
120
|
return `logged in!`
|
|
121
121
|
})
|
|
@@ -139,10 +139,10 @@ In the last example we used interfaces to define the types for the request query
|
|
|
139
139
|
"title": "Headers Schema",
|
|
140
140
|
"type": "object",
|
|
141
141
|
"properties": {
|
|
142
|
-
"
|
|
142
|
+
"h-Custom": { "type": "string" }
|
|
143
143
|
},
|
|
144
144
|
"additionalProperties": false,
|
|
145
|
-
"required": ["
|
|
145
|
+
"required": ["h-Custom"]
|
|
146
146
|
}
|
|
147
147
|
```
|
|
148
148
|
```json
|
|
@@ -194,7 +194,7 @@ In the last example we used interfaces to define the types for the request query
|
|
|
194
194
|
done(username !== 'admin' ? new Error('Must be admin') : undefined)
|
|
195
195
|
}
|
|
196
196
|
}, async (request, reply) => {
|
|
197
|
-
const customerHeader = request.headers['
|
|
197
|
+
const customerHeader = request.headers['h-Custom']
|
|
198
198
|
// do something with request data
|
|
199
199
|
return `logged in!`
|
|
200
200
|
})
|
|
@@ -211,11 +211,11 @@ In the last example we used interfaces to define the types for the request query
|
|
|
211
211
|
},
|
|
212
212
|
preHandler: (request, reply) => {
|
|
213
213
|
const { username, password } = request.query
|
|
214
|
-
const customerHeader = request.headers['
|
|
214
|
+
const customerHeader = request.headers['h-Custom']
|
|
215
215
|
},
|
|
216
216
|
handler: (request, reply) => {
|
|
217
217
|
const { username, password } = request.query
|
|
218
|
-
const customerHeader = request.headers['
|
|
218
|
+
const customerHeader = request.headers['h-Custom']
|
|
219
219
|
}
|
|
220
220
|
})
|
|
221
221
|
|
|
@@ -229,7 +229,7 @@ In the last example we used interfaces to define the types for the request query
|
|
|
229
229
|
```
|
|
230
230
|
Pay special attention to the imports at the top of this file. It might seem redundant, but you need to import both the schema files and the generated interfaces.
|
|
231
231
|
|
|
232
|
-
Great work! Now you can make use of both JSON Schemas and TypeScript definitions. If you didn't know already, defining schemas for your Fastify routes can increase their throughput! Check out the [Validation and Serialization](Validation-and-Serialization.md)
|
|
232
|
+
Great work! Now you can make use of both JSON Schemas and TypeScript definitions. If you didn't know already, defining schemas for your Fastify routes can increase their throughput! Check out the [Validation and Serialization](Validation-and-Serialization.md) documentation for more info.
|
|
233
233
|
|
|
234
234
|
Some additional notes:
|
|
235
235
|
- Currently, there is no type definition support for inline JSON schemas. If you can come up with a solution please open a PR!
|
|
@@ -333,14 +333,14 @@ This plugin guide is for Fastify plugins written in JavaScript. The steps outlin
|
|
|
333
333
|
// fastify-plugin is highly recommended for any plugin you write
|
|
334
334
|
const fp = require('fastify-plugin')
|
|
335
335
|
|
|
336
|
-
function myPlugin (instance, options,
|
|
336
|
+
function myPlugin (instance, options, done) {
|
|
337
337
|
|
|
338
338
|
// decorate the fastify instance with a custom function called myPluginFunc
|
|
339
339
|
instance.decorate('myPluginFunc', (input) => {
|
|
340
340
|
return input.toUpperCase()
|
|
341
341
|
})
|
|
342
342
|
|
|
343
|
-
|
|
343
|
+
done()
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
module.exports = fp(myPlugin, {
|
|
@@ -393,6 +393,23 @@ However, there are a couple of suggestions to help improve this experience:
|
|
|
393
393
|
- Make sure the `no-unused-vars` rule is enabled in [ESLint](https://eslint.org/docs/rules/no-unused-vars) and any imported plugin are actually being loaded.
|
|
394
394
|
- Use a module such as [depcheck](https://www.npmjs.com/package/depcheck) or [npm-check](https://www.npmjs.com/package/npm-check) to verify plugin dependencies are being used somewhere in your project.
|
|
395
395
|
|
|
396
|
+
## Code Completion In Vanilla JavaScript
|
|
397
|
+
|
|
398
|
+
Vanilla JavaScript can use the published types to provide code completion (e.g. [Intellisense](https://code.visualstudio.com/docs/editor/intellisense)) by following the [TypeScript JSDoc Reference](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html).
|
|
399
|
+
|
|
400
|
+
For example:
|
|
401
|
+
|
|
402
|
+
```js
|
|
403
|
+
/**
|
|
404
|
+
* setup some routes
|
|
405
|
+
* @param {import("fastify").FastifyInstance} fastify
|
|
406
|
+
* @param {*} opts
|
|
407
|
+
*/
|
|
408
|
+
module.exports = async function (fastify, opts) {
|
|
409
|
+
fastify.get('/look', () => 'at me');
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
396
413
|
## API Type System Documentation
|
|
397
414
|
|
|
398
415
|
This section is a detailed account of all the types available to you in Fastify version 3.x
|
|
@@ -588,7 +605,7 @@ server.get('/', async (request, reply) => {
|
|
|
588
605
|
|
|
589
606
|
###### Example 5: Specifying logger types
|
|
590
607
|
|
|
591
|
-
Fastify uses [Pino](
|
|
608
|
+
Fastify uses [Pino](https://getpino.io/#/) logging library under the hood. Some of it's properties can be configured via `logger` field when constructing Fastify's instance. If properties you need aren't exposed, it's also possible to pass a preconfigured external instance of Pino (or any other compatible logger) to Fastify via the same field. This allows creating custom serializers as well, see the [Logging](Logging.md) documentation for more info.
|
|
592
609
|
|
|
593
610
|
To use an external instance of Pino, add `@types/pino` to devDependencies and pass the instance to `logger` field:
|
|
594
611
|
|
|
@@ -839,7 +856,7 @@ const server = fastify()
|
|
|
839
856
|
const plugin: FastifyPlugin<{
|
|
840
857
|
option1: string;
|
|
841
858
|
option2: boolean;
|
|
842
|
-
}> = function (instance, opts,
|
|
859
|
+
}> = function (instance, opts, done) { }
|
|
843
860
|
|
|
844
861
|
fastify().register(plugin, {}) // Error - options object is missing required properties
|
|
845
862
|
fastify().register(plugin, { option1: '', option2: true }) // OK - options object contains required properties
|
|
@@ -862,7 +879,7 @@ Check out the [Specifying Logger Types](#example-5-specifying-logger-types) exam
|
|
|
862
879
|
|
|
863
880
|
[src](../types/logger.d.ts#L17)
|
|
864
881
|
|
|
865
|
-
An interface definition for the internal Fastify logger. It is emulative of the [Pino.js](
|
|
882
|
+
An interface definition for the internal Fastify logger. It is emulative of the [Pino.js](https://getpino.io/#/) logger. When enabled through server options, use it following the general [logger](Logging.md) documentation.
|
|
866
883
|
|
|
867
884
|
##### fastify.FastifyLogFn
|
|
868
885
|
|
|
@@ -985,7 +1002,7 @@ This interface is passed to instance of FastifyError.
|
|
|
985
1002
|
|
|
986
1003
|
#### Hooks
|
|
987
1004
|
|
|
988
|
-
##### fastify.
|
|
1005
|
+
##### fastify.onRequestHookHandler<[RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
989
1006
|
|
|
990
1007
|
[src](../types/hooks.d.ts#L17)
|
|
991
1008
|
|
|
@@ -993,7 +1010,7 @@ This interface is passed to instance of FastifyError.
|
|
|
993
1010
|
|
|
994
1011
|
Notice: in the `onRequest` hook, request.body will always be null, because the body parsing happens before the `preHandler` hook.
|
|
995
1012
|
|
|
996
|
-
##### fastify.
|
|
1013
|
+
##### fastify.preParsingHookHandler<[RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
997
1014
|
|
|
998
1015
|
[src](../types/hooks.d.ts#L35)
|
|
999
1016
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<h1 align="center">Fastify</h1>
|
|
2
2
|
|
|
3
3
|
## Validation and Serialization
|
|
4
|
-
Fastify uses a schema-based approach, and even if it is not mandatory we recommend using [JSON Schema](
|
|
4
|
+
Fastify uses a schema-based approach, and even if it is not mandatory we recommend using [JSON Schema](https://json-schema.org/) to validate your routes and serialize your outputs. Internally, Fastify compiles the schema into a highly performant function.
|
|
5
5
|
|
|
6
6
|
> ## ⚠ Security Notice
|
|
7
7
|
> Treat the schema definition as application code.
|
|
8
8
|
> As both validation and serialization features dynamically evaluate
|
|
9
9
|
> code with `new Function()`, it is not safe to use
|
|
10
|
-
> user-provided schemas. See [Ajv](
|
|
11
|
-
> [fast-json-stringify](
|
|
10
|
+
> user-provided schemas. See [Ajv](https://npm.im/ajv) and
|
|
11
|
+
> [fast-json-stringify](https://npm.im/fast-json-stringify) for more
|
|
12
12
|
> details.
|
|
13
13
|
|
|
14
14
|
|
|
@@ -731,7 +731,7 @@ const refToSharedSchemaDefinitions = {
|
|
|
731
731
|
|
|
732
732
|
<a name="resources"></a>
|
|
733
733
|
### Resources
|
|
734
|
-
- [JSON Schema](
|
|
734
|
+
- [JSON Schema](https://json-schema.org/)
|
|
735
735
|
- [Understanding JSON Schema](https://spacetelescope.github.io/understanding-json-schema/)
|
|
736
736
|
- [fast-json-stringify documentation](https://github.com/fastify/fast-json-stringify)
|
|
737
737
|
- [Ajv documentation](https://github.com/epoberezkin/ajv/blob/master/README.md)
|
package/docs/Write-Plugin.md
CHANGED
|
@@ -9,7 +9,7 @@ The core principles of Fastify are performance, low overhead and providing a goo
|
|
|
9
9
|
## Code
|
|
10
10
|
Fastify uses different techniques to optimize its code, many of them are documented in our Guides. We highly recommend you read [the hitchhiker's guide to plugins](Plugins-Guide.md) to discover all the APIs you can use to build your plugin and learn how use them.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Do you have a question or need some advice? We are more than happy to help you! Just open an issue in our [help repository](https://github.com/fastify/help).
|
|
13
13
|
|
|
14
14
|
Once you submit a plugin to our [ecosystem list](Ecosystem.md), we will review your code and help you improve it if necessary.
|
|
15
15
|
|
|
@@ -33,7 +33,7 @@ Always put an example file in your repository. Examples are very helpful for use
|
|
|
33
33
|
It is extremely important that a plugin is thoroughly tested to verify that is working properly.<br>
|
|
34
34
|
A plugin without tests will not be accepted to the ecosystem list. A lack of tests does not inspire trust nor guarantee that the code will continue to work among different versions of its dependencies.
|
|
35
35
|
|
|
36
|
-
We do not enforce any testing library. We use [`tap`](
|
|
36
|
+
We do not enforce any testing library. We use [`tap`](https://www.node-tap.org/) since it offers out of the box parallel testing and code coverage, but it is up to you to choose your library of preference.
|
|
37
37
|
|
|
38
38
|
## Code Linter
|
|
39
39
|
It is not mandatory, but we highly recommend you use a code linter in your plugin. It will ensure a consistent code style and help you to avoid many errors.
|
|
@@ -41,8 +41,8 @@ It is not mandatory, but we highly recommend you use a code linter in your plugi
|
|
|
41
41
|
We use [`standard`](https://standardjs.com/) since it works without the need to configure it and is very easy integrate in a test suite.
|
|
42
42
|
|
|
43
43
|
## Continuous Integration
|
|
44
|
-
It is not mandatory, but if you release your code as open source it helps to use Continuous Integration to ensure contributions do not break your plugin and to show that the plugin works as intended. [
|
|
45
|
-
In addition you can enable services like [
|
|
44
|
+
It is not mandatory, but if you release your code as open source it helps to use Continuous Integration to ensure contributions do not break your plugin and to show that the plugin works as intended. Both [CircleCI](https://circleci.com/) and [GitHub Actions](https://github.com/features/actions) are free for open source projects and easy to setup.<br>
|
|
45
|
+
In addition you can enable services like [Dependabot](https://dependabot.com/) or [Snyk](https://snyk.io/), that will help you keep your dependencies up to date and discover if a new release of Fastify has some issues with your plugin.
|
|
46
46
|
|
|
47
47
|
## Let's start!
|
|
48
48
|
Awesome, now you know everything you need to know about how to write a good plugin for Fastify!
|
|
@@ -18,27 +18,27 @@ const opts = {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
fastify
|
|
21
|
-
.addHook('onRequest', function (request, reply,
|
|
22
|
-
|
|
21
|
+
.addHook('onRequest', function (request, reply, done) {
|
|
22
|
+
done()
|
|
23
23
|
})
|
|
24
|
-
.addHook('onRequest', function (request, reply,
|
|
25
|
-
|
|
24
|
+
.addHook('onRequest', function (request, reply, done) {
|
|
25
|
+
done()
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
fastify
|
|
29
|
-
.addHook('preHandler', function (request, reply,
|
|
30
|
-
|
|
29
|
+
.addHook('preHandler', function (request, reply, done) {
|
|
30
|
+
done()
|
|
31
31
|
})
|
|
32
|
-
.addHook('preHandler', function (request, reply,
|
|
33
|
-
setImmediate(
|
|
32
|
+
.addHook('preHandler', function (request, reply, done) {
|
|
33
|
+
setImmediate(done)
|
|
34
34
|
})
|
|
35
|
-
.addHook('preHandler', function (request, reply,
|
|
36
|
-
|
|
35
|
+
.addHook('preHandler', function (request, reply, done) {
|
|
36
|
+
done()
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
fastify
|
|
40
|
-
.addHook('onSend', function (request, reply, payload,
|
|
41
|
-
|
|
40
|
+
.addHook('onSend', function (request, reply, payload, done) {
|
|
41
|
+
done()
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
fastify.get('/', opts, function (request, reply) {
|
package/examples/hooks.js
CHANGED
|
@@ -33,37 +33,37 @@ const optsPost = {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
fastify
|
|
36
|
-
.addHook('onRequest', function (request, reply,
|
|
36
|
+
.addHook('onRequest', function (request, reply, done) {
|
|
37
37
|
console.log('onRequest')
|
|
38
|
-
|
|
38
|
+
done()
|
|
39
39
|
})
|
|
40
|
-
.addHook('preParsing', function (request, reply,
|
|
40
|
+
.addHook('preParsing', function (request, reply, done) {
|
|
41
41
|
console.log('preParsing')
|
|
42
|
-
|
|
42
|
+
done()
|
|
43
43
|
})
|
|
44
|
-
.addHook('preValidation', function (request, reply,
|
|
44
|
+
.addHook('preValidation', function (request, reply, done) {
|
|
45
45
|
console.log('preValidation')
|
|
46
|
-
|
|
46
|
+
done()
|
|
47
47
|
})
|
|
48
|
-
.addHook('preHandler', function (request, reply,
|
|
48
|
+
.addHook('preHandler', function (request, reply, done) {
|
|
49
49
|
console.log('preHandler')
|
|
50
|
-
|
|
50
|
+
done()
|
|
51
51
|
})
|
|
52
|
-
.addHook('preSerialization', function (request, reply, payload,
|
|
52
|
+
.addHook('preSerialization', function (request, reply, payload, done) {
|
|
53
53
|
console.log('preSerialization', payload)
|
|
54
|
-
|
|
54
|
+
done()
|
|
55
55
|
})
|
|
56
|
-
.addHook('onError', function (request, reply, error,
|
|
56
|
+
.addHook('onError', function (request, reply, error, done) {
|
|
57
57
|
console.log('onError', error.message)
|
|
58
|
-
|
|
58
|
+
done()
|
|
59
59
|
})
|
|
60
|
-
.addHook('onSend', function (request, reply, payload,
|
|
60
|
+
.addHook('onSend', function (request, reply, payload, done) {
|
|
61
61
|
console.log('onSend', payload)
|
|
62
|
-
|
|
62
|
+
done()
|
|
63
63
|
})
|
|
64
|
-
.addHook('onResponse', function (request, reply,
|
|
64
|
+
.addHook('onResponse', function (request, reply, done) {
|
|
65
65
|
console.log('onResponse')
|
|
66
|
-
|
|
66
|
+
done()
|
|
67
67
|
})
|
|
68
68
|
.addHook('onRoute', function (routeOptions) {
|
|
69
69
|
console.log('onRoute')
|
package/examples/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
module.exports = function (fastify, opts,
|
|
3
|
+
module.exports = function (fastify, opts, done) {
|
|
4
4
|
fastify
|
|
5
5
|
.get('/', opts, function (req, reply) {
|
|
6
6
|
reply.send({ hello: 'world' })
|
|
@@ -8,5 +8,5 @@ module.exports = function (fastify, opts, next) {
|
|
|
8
8
|
.post('/', opts, function (req, reply) {
|
|
9
9
|
reply.send({ hello: 'world' })
|
|
10
10
|
})
|
|
11
|
-
|
|
11
|
+
done()
|
|
12
12
|
}
|
package/examples/route-prefix.js
CHANGED
|
@@ -15,20 +15,20 @@ const opts = {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
fastify.register(function (instance, options,
|
|
18
|
+
fastify.register(function (instance, options, done) {
|
|
19
19
|
// the route will be '/english/hello'
|
|
20
20
|
instance.get('/hello', opts, (req, reply) => {
|
|
21
21
|
reply.send({ greet: 'hello' })
|
|
22
22
|
})
|
|
23
|
-
|
|
23
|
+
done()
|
|
24
24
|
}, { prefix: '/english' })
|
|
25
25
|
|
|
26
|
-
fastify.register(function (instance, options,
|
|
26
|
+
fastify.register(function (instance, options, done) {
|
|
27
27
|
// the route will be '/italian/hello'
|
|
28
28
|
instance.get('/hello', opts, (req, reply) => {
|
|
29
29
|
reply.send({ greet: 'ciao' })
|
|
30
30
|
})
|
|
31
|
-
|
|
31
|
+
done()
|
|
32
32
|
}, { prefix: '/italian' })
|
|
33
33
|
|
|
34
34
|
fastify.listen(8000, function (err) {
|
package/fastify.d.ts
CHANGED
|
@@ -83,6 +83,7 @@ export type FastifyServerOptions<
|
|
|
83
83
|
bodyLimit?: number,
|
|
84
84
|
maxParamLength?: number,
|
|
85
85
|
disableRequestLogging?: boolean,
|
|
86
|
+
exposeHeadRoutes?: boolean,
|
|
86
87
|
onProtoPoisoning?: 'error' | 'remove' | 'ignore',
|
|
87
88
|
onConstructorPoisoning?: 'error' | 'remove' | 'ignore',
|
|
88
89
|
logger?: boolean | FastifyLoggerOptions<RawServer> | Logger,
|
|
@@ -118,6 +119,20 @@ export type FastifyServerOptions<
|
|
|
118
119
|
|
|
119
120
|
type TrustProxyFunction = (address: string, hop: number) => boolean
|
|
120
121
|
|
|
122
|
+
declare module 'fastify-error' {
|
|
123
|
+
interface FastifyError {
|
|
124
|
+
validation?: ValidationResult[];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface ValidationResult {
|
|
129
|
+
keyword: string;
|
|
130
|
+
dataPath: string;
|
|
131
|
+
schemaPath: string;
|
|
132
|
+
params: Record<string, string | string[]>;
|
|
133
|
+
message: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
121
136
|
/* Export all additional types */
|
|
122
137
|
export { FastifyRequest, RequestGenericInterface } from './types/request'
|
|
123
138
|
export { FastifyReply } from './types/reply'
|
|
@@ -128,7 +143,7 @@ export { FastifyContext } from './types/context'
|
|
|
128
143
|
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler } from './types/route'
|
|
129
144
|
export * from './types/register'
|
|
130
145
|
export { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser } from './types/content-type-parser'
|
|
131
|
-
export { FastifyError
|
|
146
|
+
export { FastifyError } from 'fastify-error'
|
|
132
147
|
export { FastifySchema, FastifySchemaCompiler } from './types/schema'
|
|
133
148
|
export { HTTPMethods, RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault, ContextConfigDefault, RequestBodyDefault, RequestQuerystringDefault, RequestParamsDefault, RequestHeadersDefault } from './types/utils'
|
|
134
149
|
export * from './types/hooks'
|