fastify 2.7.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -4
- package/build/build-validation.js +8 -0
- package/docs/Benchmarking.md +2 -2
- package/docs/ContentTypeParser.md +12 -10
- package/docs/Decorators.md +14 -14
- package/docs/Ecosystem.md +7 -1
- package/docs/Errors.md +13 -8
- package/docs/Fluent-Schema.md +9 -12
- package/docs/Getting-Started.md +29 -25
- package/docs/HTTP2.md +1 -1
- package/docs/Hooks.md +201 -186
- package/docs/LTS.md +6 -7
- package/docs/Logging.md +10 -10
- package/docs/Middleware.md +59 -0
- package/docs/Plugins-Guide.md +52 -52
- package/docs/Plugins.md +3 -0
- package/docs/Reply.md +47 -3
- package/docs/Routes.md +120 -8
- package/docs/Server.md +69 -3
- package/docs/Serverless.md +76 -4
- package/docs/TypeScript.md +33 -10
- package/docs/Validation-and-Serialization.md +137 -1
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +52 -13
- package/fastify.js +68 -7
- package/lib/configValidator.js +99 -52
- package/lib/contentTypeParser.js +4 -4
- package/lib/context.js +2 -1
- package/lib/errors.js +21 -18
- package/lib/fourOhFour.js +10 -10
- package/lib/handleRequest.js +1 -2
- package/lib/logger.js +2 -2
- package/lib/pluginUtils.js +32 -0
- package/lib/reply.js +41 -6
- package/lib/route.js +37 -9
- package/lib/schemas.js +23 -12
- package/lib/symbols.js +4 -1
- package/lib/validation.js +15 -9
- package/lib/wrapThenable.js +1 -1
- package/package.json +34 -26
- package/test/404s.test.js +41 -1
- package/test/async-await.js +66 -0
- package/test/custom-parser.test.js +1 -1
- package/test/custom-querystring-parser.test.js +1 -1
- package/test/decorator.test.js +48 -0
- package/test/emit-warning.test.js +3 -3
- package/test/fastify-instance.test.js +29 -0
- package/test/helper.js +7 -7
- package/test/hooks-async.js +4 -3
- package/test/hooks.test.js +27 -8
- package/test/input-validation.test.js +126 -0
- package/test/internals/errors.test.js +9 -1
- package/test/internals/initialConfig.test.js +4 -2
- package/test/internals/plugin.test.js +4 -4
- package/test/internals/reply.test.js +78 -6
- package/test/internals/schemas.test.js +30 -0
- package/test/internals/validation.test.js +18 -0
- package/test/listen.test.js +1 -1
- package/test/logger.test.js +314 -1
- package/test/plugin.test.js +171 -0
- package/test/promises.test.js +55 -0
- package/test/proto-poisoning.test.js +76 -0
- package/test/route-hooks.test.js +109 -91
- package/test/route-prefix.test.js +1 -1
- package/test/schemas.test.js +450 -0
- package/test/shared-schemas.test.js +2 -2
- package/test/stream.test.js +10 -6
- package/test/throw.test.js +48 -2
- package/test/types/index.ts +86 -1
- package/test/validation-error-handling.test.js +3 -3
- package/test/versioned-routes.test.js +1 -1
- package/docs/Middlewares.md +0 -59
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<h1 align="center">Fastify</h1>
|
|
2
|
+
|
|
3
|
+
## Middleware
|
|
4
|
+
|
|
5
|
+
Fastify provides an asynchronous [middleware engine](https://github.com/fastify/middie) out-of-the-box, which is compatible with [Express](https://expressjs.com/) and [Restify](http://restify.com/) middleware.
|
|
6
|
+
|
|
7
|
+
*For help with understanding when middleware is executed, take a look at the [lifecycle](https://github.com/fastify/fastify/blob/master/docs/Lifecycle.md) page.*
|
|
8
|
+
|
|
9
|
+
Fastify middleware don't support the full syntax `middleware(err, req, res, next)`, because error handling is done inside Fastify.
|
|
10
|
+
Furthermore, methods added by Express and Restify to the enhanced versions of `req` and `res` are not supported in Fastify middlewares.
|
|
11
|
+
|
|
12
|
+
Also, if you are using middleware that bundles different, smaller middleware, such as [*helmet*](https://helmetjs.github.io/), we recommend using the single modules for better performance.
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
fastify.use(require('cors')())
|
|
16
|
+
fastify.use(require('dns-prefetch-control')())
|
|
17
|
+
fastify.use(require('frameguard')())
|
|
18
|
+
fastify.use(require('hide-powered-by')())
|
|
19
|
+
fastify.use(require('hsts')())
|
|
20
|
+
fastify.use(require('ienoopen')())
|
|
21
|
+
fastify.use(require('x-xss-protection')())
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
or, in the specific case of *helmet*, you can use the [*fastify-helmet*](https://github.com/fastify/fastify-helmet) [plugin](Plugins.md), which is an optimized helmet integration for fastify:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
const fastify = require('fastify')()
|
|
28
|
+
const helmet = require('fastify-helmet')
|
|
29
|
+
|
|
30
|
+
fastify.register(helmet)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Remember that middleware can be encapsulated, this means that you can decide where your middleware should run by using `register` as explained in the [plugins guide](https://github.com/fastify/fastify/blob/master/docs/Plugins-Guide.md).
|
|
34
|
+
|
|
35
|
+
Fastify middleware also do not expose the `send` method or other methods specific to the Fastify [Reply]('./Reply.md' "Reply") instance. This is because Fastify wraps the incoming `req` and `res` Node instances using the [Request](./Request.md "Request") and [Reply](./Reply.md "Reply") objects internally, but this is done after the middleware phase. If you need to create middleware, you have to use the Node `req` and `res` instances. Otherwise, you can use the `preHandler` hook which already has the [Request](./Request.md "Request") and [Reply](./Reply.md "Reply") Fastify instances. For more information, see [Hooks](./Hooks.md "Hooks").
|
|
36
|
+
|
|
37
|
+
<a name="restrict-usage"></a>
|
|
38
|
+
#### Restrict middleware execution to a certain path(s)
|
|
39
|
+
If you need to run a middleware only under certain path(s), just pass the path as first parameter to `use` and you are done!
|
|
40
|
+
|
|
41
|
+
*Note that this does not support routes with parameters, (eg: `/user/:id/comments`) and wildcards are not supported in multiple paths.*
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
const path = require('path')
|
|
45
|
+
const serveStatic = require('serve-static')
|
|
46
|
+
|
|
47
|
+
// Single path
|
|
48
|
+
fastify.use('/css', serveStatic(path.join(__dirname, '/assets')))
|
|
49
|
+
|
|
50
|
+
// Wildcard path
|
|
51
|
+
fastify.use('/css/*', serveStatic(path.join(__dirname, '/assets')))
|
|
52
|
+
|
|
53
|
+
// Multiple paths
|
|
54
|
+
fastify.use(['/css', '/js'], serveStatic(path.join(__dirname, '/assets')))
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
<a name="express-middleware"></a>
|
|
58
|
+
#### Express middleware compatibility
|
|
59
|
+
Express modifies the prototype of the node core Request and Response objects heavily so Fastify cannot guarantee full middleware compatibility. Express specific functionality such as `res.sendFile()`, `res.send()` or `express.Router()` instances will not work with Fastify. For example, [cors](https://github.com/expressjs/cors) is compatible while [passport](https://github.com/jaredhanson/passport) is not.
|
package/docs/Plugins-Guide.md
CHANGED
|
@@ -16,30 +16,29 @@ Fastify was built from the beginning to be an extremely modular system. We built
|
|
|
16
16
|
|
|
17
17
|
<a name="register"></a>
|
|
18
18
|
## Register
|
|
19
|
-
As
|
|
20
|
-
Your routes, your utilities and so on are all plugins. To add a new plugin, whatever its functionality
|
|
19
|
+
As with JavaScript, where everything is an object, in Fastify everything is a plugin.<br>
|
|
20
|
+
Your routes, your utilities and so on are all plugins. To add a new plugin, whatever its functionality may be, in Fastify you have a nice and unique API: [`register`](https://github.com/fastify/fastify/blob/master/docs/Plugins.md).
|
|
21
21
|
```js
|
|
22
22
|
fastify.register(
|
|
23
23
|
require('./my-plugin'),
|
|
24
24
|
{ options }
|
|
25
25
|
)
|
|
26
26
|
```
|
|
27
|
-
`register` creates a new Fastify context,
|
|
28
|
-
|
|
27
|
+
`register` creates a new Fastify context, which means that if you perform any changes on the Fastify instance, those changes will not be reflected in the context's ancestors. In other words, encapsulation!
|
|
29
28
|
|
|
30
29
|
*Why is encapsulation important?*<br>
|
|
31
|
-
Well, let's say you are creating a new disruptive startup, what do you do? You create an
|
|
32
|
-
Ok, you are growing very fast and you want to change your architecture and try microservices. Usually this implies a huge amount of work, because of cross dependencies and
|
|
33
|
-
Fastify helps you
|
|
30
|
+
Well, let's say you are creating a new disruptive startup, what do you do? You create an API server with all your stuff, everything in the same place, a monolith!<br>
|
|
31
|
+
Ok, you are growing very fast and you want to change your architecture and try microservices. Usually, this implies a huge amount of work, because of cross dependencies and a lack of separation of concerns in the codebase.<br>
|
|
32
|
+
Fastify helps you in that regard. Thanks to the encapsulation model it will completely avoid cross dependencies, and will help you structure your code into cohesive blocks.
|
|
34
33
|
|
|
35
34
|
*Let's return to how to correctly use `register`.*<br>
|
|
36
35
|
As you probably know, the required plugins must expose a single function with the following signature
|
|
37
36
|
```js
|
|
38
37
|
module.exports = function (fastify, options, done) {}
|
|
39
38
|
```
|
|
40
|
-
Where `fastify` is
|
|
39
|
+
Where `fastify` is the encapsulated Fastify instance, `options` is the options object and `done` is the function you **must** call when your plugin is ready.
|
|
41
40
|
|
|
42
|
-
Fastify's plugin model is fully reentrant and graph-based, it handles without any
|
|
41
|
+
Fastify's plugin model is fully reentrant and graph-based, it handles asynchronous code without any problems and it enforces both the load and close order of plugins. *How?* Glad you asked, check out [`avvio`](https://github.com/mcollina/avvio)! Fastify starts loading the plugin __after__ `.listen()`, `.inject()` or `.ready()` are called.
|
|
43
42
|
|
|
44
43
|
Inside a plugin you can do whatever you want, register routes, utilities (we'll see this in a moment) and do nested registers, just remember to call `done` when everything is set up!
|
|
45
44
|
```js
|
|
@@ -52,11 +51,11 @@ module.exports = function (fastify, options, done) {
|
|
|
52
51
|
}
|
|
53
52
|
```
|
|
54
53
|
|
|
55
|
-
Well, now you know how to use the `register`
|
|
54
|
+
Well, now you know how to use the `register` API and how it works, but how do we add new functionality to Fastify and even better, share them with other developers?
|
|
56
55
|
|
|
57
56
|
<a name="decorators"></a>
|
|
58
57
|
## Decorators
|
|
59
|
-
Okay, let's say that you wrote
|
|
58
|
+
Okay, let's say that you wrote a utility that is so good that you decided to make it available along with all your code. How would you do it? Probably something like the following:
|
|
60
59
|
```js
|
|
61
60
|
// your-awesome-utility.js
|
|
62
61
|
module.exports = function (a, b) {
|
|
@@ -65,40 +64,42 @@ module.exports = function (a, b) {
|
|
|
65
64
|
```
|
|
66
65
|
```js
|
|
67
66
|
const util = require('./your-awesome-utility')
|
|
68
|
-
console.log(util('that is ', '
|
|
67
|
+
console.log(util('that is ', 'awesome'))
|
|
69
68
|
```
|
|
70
|
-
And now you will import your utility in every file you need it. (And don't forget that you will probably also need it in your
|
|
69
|
+
And now you will import your utility in every file you need it in. (And don't forget that you will probably also need it in your tests).
|
|
71
70
|
|
|
72
|
-
Fastify offers you a
|
|
73
|
-
|
|
71
|
+
Fastify offers you a more elegant and comfortable way to do this, *decorators*.
|
|
72
|
+
Creating a decorator is extremely easy, just use the [`decorate`](https://github.com/fastify/fastify/blob/master/docs/Decorators.md) API:
|
|
74
73
|
```js
|
|
75
74
|
fastify.decorate('util', (a, b) => a + b)
|
|
76
75
|
```
|
|
77
|
-
Now you can access your utility just by
|
|
78
|
-
And here
|
|
76
|
+
Now you can access your utility just by calling `fastify.util` whenever you need it - even inside your test.<br>
|
|
77
|
+
And here starts the magic; do you remember how just now we were talking about encapsulation? Well, using `register` and `decorate` in conjunction enable exactly that, let me show you an example to clarify this:
|
|
79
78
|
```js
|
|
80
79
|
fastify.register((instance, opts, done) => {
|
|
81
80
|
instance.decorate('util', (a, b) => a + b)
|
|
82
|
-
console.log(instance.util('that is ', '
|
|
81
|
+
console.log(instance.util('that is ', 'awesome'))
|
|
83
82
|
|
|
84
83
|
done()
|
|
85
84
|
})
|
|
86
85
|
|
|
87
86
|
fastify.register((instance, opts, done) => {
|
|
88
|
-
console.log(instance.util('that is ', '
|
|
87
|
+
console.log(instance.util('that is ', 'awesome')) // This will throw an error
|
|
89
88
|
|
|
90
89
|
done()
|
|
91
90
|
})
|
|
92
91
|
```
|
|
93
92
|
Inside the second register call `instance.util` will throw an error, because `util` exists only inside the first register context.<br>
|
|
94
|
-
Let's step back for a moment and
|
|
93
|
+
Let's step back for a moment and dig deeper into this: every time you use the `register` API, a new context is created which avoids the negative situations mentioned above.
|
|
94
|
+
|
|
95
|
+
Do note that encapsulation applies to the ancestors and siblings, but not the children.
|
|
95
96
|
```js
|
|
96
97
|
fastify.register((instance, opts, done) => {
|
|
97
98
|
instance.decorate('util', (a, b) => a + b)
|
|
98
|
-
console.log(instance.util('that is ', '
|
|
99
|
+
console.log(instance.util('that is ', 'awesome'))
|
|
99
100
|
|
|
100
101
|
fastify.register((instance, opts, done) => {
|
|
101
|
-
console.log(instance.util('that is ', '
|
|
102
|
+
console.log(instance.util('that is ', 'awesome')) // This will not throw an error
|
|
102
103
|
done()
|
|
103
104
|
})
|
|
104
105
|
|
|
@@ -106,14 +107,14 @@ fastify.register((instance, opts, done) => {
|
|
|
106
107
|
})
|
|
107
108
|
|
|
108
109
|
fastify.register((instance, opts, done) => {
|
|
109
|
-
console.log(instance.util('that is ', '
|
|
110
|
+
console.log(instance.util('that is ', 'awesome')) // This will throw an error
|
|
110
111
|
|
|
111
112
|
done()
|
|
112
113
|
})
|
|
113
114
|
```
|
|
114
|
-
*Take home message: if you need
|
|
115
|
+
*Take home message: if you need an utility which is available in every part of your application, take care that it's declared in the root scope of your application. If that's not an option you can use the `fastify-plugin` utility as described [here](#distribution).*
|
|
115
116
|
|
|
116
|
-
`decorate` is not the
|
|
117
|
+
`decorate` is not the only API that you can use to extend the server functionality, you can also use `decorateRequest` and `decorateReply`.
|
|
117
118
|
|
|
118
119
|
*`decorateRequest` and `decorateReply`? Why do we need them if we already have `decorate`?*<br>
|
|
119
120
|
Good question, we added them to make Fastify more developer-friendly. Let's see an example:
|
|
@@ -128,10 +129,10 @@ fastify.get('/html', (request, reply) => {
|
|
|
128
129
|
.send(fastify.html({ hello: 'world' }))
|
|
129
130
|
})
|
|
130
131
|
```
|
|
131
|
-
It works, but it
|
|
132
|
+
It works, but it could be way better!
|
|
132
133
|
```js
|
|
133
134
|
fastify.decorateReply('html', function (payload) {
|
|
134
|
-
this.type('text/html') //
|
|
135
|
+
this.type('text/html') // This is the 'Reply' object
|
|
135
136
|
this.send(generateHtml(payload))
|
|
136
137
|
})
|
|
137
138
|
|
|
@@ -161,7 +162,7 @@ fastify.decorateRequest('setHeader', function (header) {
|
|
|
161
162
|
this.isHappy = this.headers[header]
|
|
162
163
|
})
|
|
163
164
|
|
|
164
|
-
fastify.decorateRequest('isHappy', false) //
|
|
165
|
+
fastify.decorateRequest('isHappy', false) // This will be added to the Request object prototype, yay speed!
|
|
165
166
|
|
|
166
167
|
fastify.addHook('preHandler', (request, reply, done) => {
|
|
167
168
|
request.setHeader('happy')
|
|
@@ -173,7 +174,7 @@ fastify.get('/happiness', (request, reply) => {
|
|
|
173
174
|
})
|
|
174
175
|
```
|
|
175
176
|
|
|
176
|
-
We've seen how to extend server functionality and how handle the encapsulation system, but what if you need to add a function that must be executed every time
|
|
177
|
+
We've seen how to extend server functionality and how to handle the encapsulation system, but what if you need to add a function that must be executed every time when the server "[emits](https://github.com/fastify/fastify/blob/master/docs/Lifecycle.md)" an event?
|
|
177
178
|
|
|
178
179
|
<a name="hooks"></a>
|
|
179
180
|
## Hooks
|
|
@@ -191,9 +192,9 @@ fastify.get('/plugin2', (request, reply) => {
|
|
|
191
192
|
reply.send(request)
|
|
192
193
|
})
|
|
193
194
|
```
|
|
194
|
-
I think we all agree that this is terrible.
|
|
195
|
+
I think we all agree that this is terrible. Repeated code, awful readability and it cannot scale.
|
|
195
196
|
|
|
196
|
-
So what can you do to avoid this annoying issue? Yes, you are right, use
|
|
197
|
+
So what can you do to avoid this annoying issue? Yes, you are right, use a [hook](https://github.com/fastify/fastify/blob/master/docs/Hooks.md)!<br>
|
|
197
198
|
```js
|
|
198
199
|
fastify.decorate('util', (request, key, value) => { request[key] = value })
|
|
199
200
|
|
|
@@ -210,8 +211,8 @@ fastify.get('/plugin2', (request, reply) => {
|
|
|
210
211
|
reply.send(request)
|
|
211
212
|
})
|
|
212
213
|
```
|
|
213
|
-
Now for every request you will run your utility
|
|
214
|
-
|
|
214
|
+
Now for every request, you will run your utility. Obviously you can register as many hooks as you need.<br>
|
|
215
|
+
Sometimes you want a hook that should be executed for just a subset of routes, how can you do that? Yep, encapsulation!
|
|
215
216
|
|
|
216
217
|
```js
|
|
217
218
|
fastify.register((instance, opts, done) => {
|
|
@@ -235,13 +236,13 @@ fastify.get('/plugin2', (request, reply) => {
|
|
|
235
236
|
```
|
|
236
237
|
Now your hook will run just for the first route!
|
|
237
238
|
|
|
238
|
-
As you probably noticed
|
|
239
|
+
As you probably noticed by now, `request` and `reply` are not the standard Nodejs *request* and *response* objects, but Fastify's objects.<br>
|
|
239
240
|
|
|
240
|
-
<a name="
|
|
241
|
-
##
|
|
242
|
-
Fastify [supports](https://github.com/fastify/fastify/blob/master/docs/
|
|
243
|
-
Let's say that you are arriving from Express, and you already have some Middleware
|
|
244
|
-
How we can do that?
|
|
241
|
+
<a name="middleware"></a>
|
|
242
|
+
## Middleware
|
|
243
|
+
Fastify [supports](https://github.com/fastify/fastify/blob/master/docs/Middleware.md) Express/Restify/Connect middleware out-of-the-box, which means that you can just drop-in your old code and it will work! *(faster, by the way)*<br>
|
|
244
|
+
Let's say that you are arriving from Express, and you already have some Middleware which does exactly what you need, and you don't want to redo all the work.
|
|
245
|
+
How we can do that? Check out our middleware engine, [middie](https://github.com/fastify/middie).
|
|
245
246
|
```js
|
|
246
247
|
const yourMiddleware = require('your-middleware')
|
|
247
248
|
fastify.use(yourMiddleware)
|
|
@@ -249,13 +250,12 @@ fastify.use(yourMiddleware)
|
|
|
249
250
|
|
|
250
251
|
<a name="distribution"></a>
|
|
251
252
|
## How to handle encapsulation and distribution
|
|
252
|
-
Perfect, now you know (almost) all the tools that you can use to extend Fastify. But
|
|
253
|
-
How can you distribute your code?
|
|
253
|
+
Perfect, now you know (almost) all of the tools that you can use to extend Fastify. But chances are that you came across one big issue: how is distribution handled?
|
|
254
254
|
|
|
255
|
-
The preferred way to distribute a utility is to wrap all your code inside a `register`, in this way your plugin can support
|
|
255
|
+
The preferred way to distribute a utility is to wrap all your code inside a `register`, in this way your plugin can support asynchronous bootstrapping *(since `decorate` is a synchronous API)*, in the case of a database connection for example.
|
|
256
256
|
|
|
257
|
-
*Wait, what? Didn't you tell me that `register` creates an encapsulation and that
|
|
258
|
-
Yes, I said that. But what I didn't tell you, is that you can tell to Fastify to avoid this
|
|
257
|
+
*Wait, what? Didn't you tell me that `register` creates an encapsulation and that the stuff I create inside will not be available outside?*<br>
|
|
258
|
+
Yes, I said that. But what I didn't tell you, is that you can tell to Fastify to avoid this behaviour, with the [`fastify-plugin`](https://github.com/fastify/fastify-plugin) module.
|
|
259
259
|
```js
|
|
260
260
|
const fp = require('fastify-plugin')
|
|
261
261
|
const dbClient = require('db-client')
|
|
@@ -269,7 +269,7 @@ function dbPlugin (fastify, opts, done) {
|
|
|
269
269
|
|
|
270
270
|
module.exports = fp(dbPlugin)
|
|
271
271
|
```
|
|
272
|
-
You can also tell
|
|
272
|
+
You can also tell `fastify-plugin` to check the installed version of Fastify, in case you need a specific API.
|
|
273
273
|
|
|
274
274
|
As we mentioned earlier, Fastify starts loading its plugins __after__ `.listen()`, `.inject()` or `.ready()` are called and as such, __after__ they have been declared. This means that, even though the plugin may inject variables to the external fastify instance via [`decorate`](https://github.com/fastify/fastify/blob/master/docs/Decorators.md), the decorated variables will not be accessible before calling `.listen()`, `.inject()` or `.ready()`.
|
|
275
275
|
|
|
@@ -295,14 +295,14 @@ In the above example, the `parent` variable of the function passed in as the sec
|
|
|
295
295
|
|
|
296
296
|
<a name="handle-errors"></a>
|
|
297
297
|
## Handle errors
|
|
298
|
-
It can happen that one of your plugins
|
|
299
|
-
The `after`
|
|
300
|
-
The callback changes based on the parameters
|
|
298
|
+
It can happen that one of your plugins fails during startup. Maybe you expect it and you have a custom logic that will be triggered in that case. How can you implement this?
|
|
299
|
+
The `after` API is what you need. `after` simply registers a callback that will be executed just after a register, and it can take up to three parameters.<br>
|
|
300
|
+
The callback changes based on the parameters you are giving:
|
|
301
301
|
|
|
302
302
|
1. If no parameter is given to the callback and there is an error, that error will be passed to the next error handler.
|
|
303
303
|
1. If one parameter is given to the callback, that parameter will be the error object.
|
|
304
304
|
1. If two parameters are given to the callback, the first will be the error object, the second will be the done callback.
|
|
305
|
-
1. If three parameters are given to the callback, the first will be the error object, the second will be the top
|
|
305
|
+
1. If three parameters are given to the callback, the first will be the error object, the second will be the top-level context unless you have specified both server and override, in that case, the context will be what the override returns, and the third the done callback.
|
|
306
306
|
|
|
307
307
|
Let's see how to use it:
|
|
308
308
|
```js
|
|
@@ -317,14 +317,14 @@ fastify
|
|
|
317
317
|
## Let's start!
|
|
318
318
|
Awesome, now you know everything you need to know about Fastify and its plugin system to start building your first plugin, and please if you do, tell us! We will add it to the [*ecosystem*](https://github.com/fastify/fastify#ecosystem) section of our documentation!
|
|
319
319
|
|
|
320
|
-
If you want to see some real
|
|
320
|
+
If you want to see some real-world example, check out:
|
|
321
321
|
- [`point-of-view`](https://github.com/fastify/point-of-view)
|
|
322
322
|
Templates rendering (*ejs, pug, handlebars, marko*) plugin support for Fastify.
|
|
323
323
|
- [`fastify-mongodb`](https://github.com/fastify/fastify-mongodb)
|
|
324
|
-
Fastify MongoDB connection plugin, with this you can share the same
|
|
324
|
+
Fastify MongoDB connection plugin, with this you can share the same MongoDB connection pool in every part of your server.
|
|
325
325
|
- [`fastify-multipart`](https://github.com/fastify/fastify-multipart)
|
|
326
326
|
Multipart support for Fastify
|
|
327
327
|
- [`fastify-helmet`](https://github.com/fastify/fastify-helmet) Important security headers for Fastify
|
|
328
328
|
|
|
329
329
|
|
|
330
|
-
*Do you feel
|
|
330
|
+
*Do you feel like something is missing here? Let us know! :)*
|
package/docs/Plugins.md
CHANGED
|
@@ -16,8 +16,11 @@ fastify.register(plugin, [options])
|
|
|
16
16
|
The optional `options` parameter for `fastify.register` supports a predefined set of options that Fastify itself will use, except when the plugin has been wrapped with [fastify-plugin](https://github.com/fastify/fastify-plugin). This options object will also be passed to the plugin upon invocation, regardless of whether or not the plugin has been wrapped. The currently supported list of Fastify specific options is:
|
|
17
17
|
|
|
18
18
|
+ [`logLevel`](https://github.com/fastify/fastify/blob/master/docs/Routes.md#custom-log-level)
|
|
19
|
+
+ [`logSerializers`](https://github.com/fastify/fastify/blob/master/docs/Routes.md#custom-log-serializer)
|
|
19
20
|
+ [`prefix`](https://github.com/fastify/fastify/blob/master/docs/Plugins.md#route-prefixing-options)
|
|
20
21
|
|
|
22
|
+
**Note: Those options will be ignored when used with fastify-plugin**
|
|
23
|
+
|
|
21
24
|
It is possible that Fastify will directly support other options in the future. Thus, to avoid collisions, a plugin should consider namespacing its options. For example, a plugin `foo` might be registered like so:
|
|
22
25
|
|
|
23
26
|
```js
|
package/docs/Reply.md
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
- [Reply](#reply)
|
|
5
5
|
- [Introduction](#introduction)
|
|
6
6
|
- [.code(statusCode)](#codestatuscode)
|
|
7
|
+
- [.statusCode](#statusCode)
|
|
7
8
|
- [.header(key, value)](#headerkey-value)
|
|
9
|
+
- [.headers(object)](#headersobject)
|
|
8
10
|
- [.getHeader(key)](#getheaderkey)
|
|
9
11
|
- [.removeHeader(key)](#removeheaderkey)
|
|
10
12
|
- [.hasHeader(key)](#hasheaderkey)
|
|
@@ -22,7 +24,8 @@
|
|
|
22
24
|
- [Errors](#errors)
|
|
23
25
|
- [Type of the final payload](#type-of-the-final-payload)
|
|
24
26
|
- [Async-Await and Promises](#async-await-and-promises)
|
|
25
|
-
|
|
27
|
+
- [.then](#then)
|
|
28
|
+
|
|
26
29
|
<a name="introduction"></a>
|
|
27
30
|
### Introduction
|
|
28
31
|
The second parameter of the handler function is `Reply`.
|
|
@@ -31,7 +34,9 @@ and properties:
|
|
|
31
34
|
|
|
32
35
|
- `.code(statusCode)` - Sets the status code.
|
|
33
36
|
- `.status(statusCode)` - An alias for `.code(statusCode)`.
|
|
37
|
+
- `.statusCode` - Read and set the HTTP status code.
|
|
34
38
|
- `.header(name, value)` - Sets a response header.
|
|
39
|
+
- `.headers(object)` - Sets all the keys of the object as a response headers.
|
|
35
40
|
- `.getHeader(name)` - Retrieve value of already set header.
|
|
36
41
|
- `.removeHeader(key)` - Remove the value of a previously set header.
|
|
37
42
|
- `.hasHeader(name)` - Determine if a header has been set.
|
|
@@ -43,7 +48,8 @@ and properties:
|
|
|
43
48
|
- `.send(payload)` - Sends the payload to the user, could be a plain text, a buffer, JSON, stream, or an Error object.
|
|
44
49
|
- `.sent` - A boolean value that you can use if you need to know if `send` has already been called.
|
|
45
50
|
- `.res` - The [`http.ServerResponse`](https://nodejs.org/dist/latest/docs/api/http.html#http_class_http_serverresponse) from Node core.
|
|
46
|
-
- `.log` -
|
|
51
|
+
- `.log` - The logger instance of the incoming request.
|
|
52
|
+
- `.request` - The incoming request.
|
|
47
53
|
|
|
48
54
|
```js
|
|
49
55
|
fastify.get('/', options, function (request, reply) {
|
|
@@ -67,6 +73,15 @@ fastify.get('/', {config: {foo: 'bar'}}, function (request, reply) {
|
|
|
67
73
|
### .code(statusCode)
|
|
68
74
|
If not set via `reply.code`, the resulting `statusCode` will be `200`.
|
|
69
75
|
|
|
76
|
+
<a name="statusCode"></a>
|
|
77
|
+
### .statusCode
|
|
78
|
+
This property reads and sets the HTTP status code. It is an alias for `reply.code()` when used as a setter.
|
|
79
|
+
```js
|
|
80
|
+
if (reply.statusCode >= 299) {
|
|
81
|
+
reply.statusCode = 500
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
70
85
|
<a name="header"></a>
|
|
71
86
|
### .header(key, value)
|
|
72
87
|
Sets a response header. If the value is omitted or undefined it is coerced
|
|
@@ -74,6 +89,16 @@ to `''`.
|
|
|
74
89
|
|
|
75
90
|
For more information, see [`http.ServerResponse#setHeader`](https://nodejs.org/dist/latest/docs/api/http.html#http_response_setheader_name_value).
|
|
76
91
|
|
|
92
|
+
<a name="headers"></a>
|
|
93
|
+
### .headers(object)
|
|
94
|
+
Sets all the keys of the object as response headers. [`.header`](#headerkey-value) will be called under the hood.
|
|
95
|
+
```js
|
|
96
|
+
reply.headers({
|
|
97
|
+
'x-foo': 'foo',
|
|
98
|
+
'x-bar': 'bar'
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
77
102
|
<a name="getHeader"></a>
|
|
78
103
|
### .getHeader(key)
|
|
79
104
|
Retrieves the value of a previously set header.
|
|
@@ -224,11 +249,12 @@ If you pass to *send* an object that is an instance of *Error*, Fastify will aut
|
|
|
224
249
|
```js
|
|
225
250
|
{
|
|
226
251
|
error: String // the http error message
|
|
252
|
+
code: String // the Fastify error code
|
|
227
253
|
message: String // the user error message
|
|
228
254
|
statusCode: Number // the http status code
|
|
229
255
|
}
|
|
230
256
|
```
|
|
231
|
-
You can add some custom property to the Error object, such as `
|
|
257
|
+
You can add some custom property to the Error object, such as `headers`, that will be used to enhance the http response.<br>
|
|
232
258
|
*Note: If you are passing an error to `send` and the statusCode is less than 400, Fastify will automatically set it at 500.*
|
|
233
259
|
|
|
234
260
|
Tip: you can simplify errors by using the [`http-errors`](https://npm.im/http-errors) module or [`fastify-sensible`](https://github.com/fastify/fastify-sensible) plugin to generate errors:
|
|
@@ -307,3 +333,21 @@ fastify.get('/teapot', async function (request, reply) => {
|
|
|
307
333
|
```
|
|
308
334
|
|
|
309
335
|
If you want to know more please review [Routes#async-await](https://github.com/fastify/fastify/blob/master/docs/Routes.md#async-await).
|
|
336
|
+
|
|
337
|
+
<a name="then"></a>
|
|
338
|
+
### .then(fullfilled, rejected)
|
|
339
|
+
|
|
340
|
+
As the name suggests, a `Reply` object can be awaited upon, i.e. `await reply` will wait until the reply is sent.
|
|
341
|
+
The `await` syntax calls the `reply.then()`.
|
|
342
|
+
|
|
343
|
+
`reply.then(fullfilled, rejected)` accepts two parameters:
|
|
344
|
+
|
|
345
|
+
- `fullfilled` will be called when a response has been fully sent,
|
|
346
|
+
- `rejected` will be called if the underlying stream had an error, e.g.
|
|
347
|
+
the socket has been destroyed.
|
|
348
|
+
|
|
349
|
+
For more details, see:
|
|
350
|
+
|
|
351
|
+
- https://github.com/fastify/fastify/issues/1864 for the discussion about this feature
|
|
352
|
+
- https://promisesaplus.com/ for the definition of thenables
|
|
353
|
+
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then for the signature
|