1 | <h1 align="center">Fastify</h1>
|
2 |
|
3 | ## Decorators
|
4 |
|
5 | If you need to add functionality to the Fastify instance, the `decorate` API is what you need.
|
6 |
|
7 | The API allows you to add new properties to the Fastify instance. A value is not restricted to a function and could also be an object or a string, for example.
|
8 |
|
9 | <a name="usage"></a>
|
10 | ### Usage
|
11 | <a name="decorate"></a>
|
12 | **decorate**
|
13 | Just call the `decorate` API and pass the name of the new property and its value.
|
14 | ```js
|
15 | fastify.decorate('utility', () => {
|
16 | // something very useful
|
17 | })
|
18 | ```
|
19 |
|
20 | As said above, you can also decorate the instance with non-function values:
|
21 | ```js
|
22 | fastify.decorate('conf', {
|
23 | db: 'some.db',
|
24 | port: 3000
|
25 | })
|
26 | ```
|
27 |
|
28 | Once you decorate the instance, you can access the value by using the name you passed as a parameter:
|
29 | ```js
|
30 | fastify.utility()
|
31 |
|
32 | console.log(fastify.conf.db)
|
33 | ```
|
34 |
|
35 | <a name="decorate-reply"></a>
|
36 | **decorateReply**
|
37 | As the name suggests, this API is needed if you want to add new methods to the `Reply` core object. Just call the `decorateReply` API and pass the name of the new property and its value:
|
38 | ```js
|
39 | fastify.decorateReply('utility', function () {
|
40 | // something very useful
|
41 | })
|
42 | ```
|
43 |
|
44 | Note: using an arrow function will break the binding of `this` to the Fastify `reply` instance.
|
45 |
|
46 | <a name="decorate-request"></a>
|
47 | **decorateRequest**
|
48 | As above, this API is needed if you want to add new methods to the `Request` core object. Just call the `decorateRequest` API and pass the name of the new property and its value:
|
49 | ```js
|
50 | fastify.decorateRequest('utility', function () {
|
51 | // something very useful
|
52 | })
|
53 | ```
|
54 |
|
55 | Note: using an arrow function will break the binding of `this` to the Fastify `request` instance.
|
56 |
|
57 | <a name="decorators-encapsulation"></a>
|
58 | #### Decorators and encapsulation
|
59 |
|
60 | If you define a decorator (using decorate, decorateRequest or decorateReply) with the same name more than once in the same **encapsulated** plugin, fastify will throw an exception.
|
61 |
|
62 | As an example, the following will throw:
|
63 |
|
64 | ```js
|
65 | const server = require('fastify')()
|
66 |
|
67 | server.decorateReply('view', function (template, args) {
|
68 | // Amazing view rendering engine.
|
69 | })
|
70 |
|
71 | server.get('/', (req, reply) => {
|
72 | reply.view('/index.html', { hello: 'world' })
|
73 | })
|
74 |
|
75 | // Somewhere else in our codebase, we define another
|
76 | // view decorator. This throws.
|
77 | server.decorateReply('view', function (template, args) {
|
78 | // another rendering engine
|
79 | })
|
80 |
|
81 | server.listen(3000)
|
82 | ```
|
83 |
|
84 |
|
85 | But this will not:
|
86 |
|
87 | ```js
|
88 | const server = require('fastify')()
|
89 |
|
90 | server.decorateReply('view', function (template, args) {
|
91 | // Amazing view rendering engine.
|
92 | })
|
93 |
|
94 | server.register(async function (server, opts) {
|
95 | // We add a view decorator to the current encapsulated
|
96 | // plugin. This will not throw as outside of this encapsulated
|
97 | // plugin view is the old one, while inside it is the new one.
|
98 | server.decorateReply('view', function (template, args) {
|
99 | // another rendering engine
|
100 | })
|
101 |
|
102 | server.get('/', (req, reply) => {
|
103 | reply.view('/index.page', { hello: 'world' })
|
104 | })
|
105 | }, { prefix: '/bar' })
|
106 |
|
107 | server.listen(3000)
|
108 | ```
|
109 |
|
110 | <a name="getters-setters"></a>
|
111 | #### Getters and Setters
|
112 |
|
113 | Decorators accept special "getter/setter" objects. These objects have functions named `getter` and `setter` (though, the `setter` function is optional). This allows defining properties via decorators. For example:
|
114 |
|
115 | ```js
|
116 | fastify.decorate('foo', {
|
117 | getter () {
|
118 | return 'a getter'
|
119 | }
|
120 | })
|
121 | ```
|
122 |
|
123 | Will define the `foo` property on the *Fastify* instance:
|
124 |
|
125 | ```js
|
126 | console.log(fastify.foo) // 'a getter'
|
127 | ```
|
128 |
|
129 | <a name="usage_notes"></a>
|
130 | #### Usage Notes
|
131 | `decorateReply` and `decorateRequest` are used to modify the `Reply` and `Request` constructors respectively by adding methods or properties. To update these properties you should directly access the desired property of the `Reply` or `Request` object.
|
132 |
|
133 | As an example let's add a user property to the `Request` object:
|
134 |
|
135 | ```js
|
136 | // Decorate request with a 'user' property
|
137 | fastify.decorateRequest('user', '')
|
138 |
|
139 | // Update our property
|
140 | fastify.addHook('preHandler', (req, reply, next) => {
|
141 | req.user = 'Bob Dylan'
|
142 | next()
|
143 | })
|
144 | // And finally access it
|
145 | fastify.get('/', (req, reply) => {
|
146 | reply.send(`Hello ${req.user}!`)
|
147 | })
|
148 | ```
|
149 | Note: The usage of `decorateReply` and `decorateRequest` is optional in this case but will allow Fastify to optimize for performance.
|
150 |
|
151 | <a name="sync-async"></a>
|
152 | #### Sync and Async
|
153 | `decorate` is a *synchronous* API. If you need to add a decorator that has an *asynchronous* bootstrap, Fastify could boot up before your decorator is ready. To avoid this issue, you must use the `register` API in combination with `fastify-plugin`. To learn more, check out the [Plugins](https://github.com/fastify/fastify/blob/master/docs/Plugins.md) documentation as well.
|
154 |
|
155 | <a name="dependencies"></a>
|
156 | #### Dependencies
|
157 | If your decorator depends on another decorator, you can easily declare the other decorator as a dependency. You just need to add an array of strings (representing the names of the decorators on which yours depends) as the third parameter:
|
158 | ```js
|
159 | fastify.decorate('utility', fn, ['greet', 'log'])
|
160 | ```
|
161 |
|
162 | If a dependency is not satisfied, `decorate` will throw an exception, but don't worry: the dependency check is executed before the server boots up, so it won't ever happen at runtime.
|
163 |
|
164 | <a name="has-decorator"></a>
|
165 | #### hasDecorator
|
166 | You can check for the presence of a decorator with the `hasDecorator` API:
|
167 | ```js
|
168 | fastify.hasDecorator('utility')
|
169 | ```
|
170 |
|
171 | <a name="has-request-decorator"></a>
|
172 | #### hasRequestDecorator
|
173 | You can check for the presence of a Request decorator with the `hasRequestDecorator` API:
|
174 | ```js
|
175 | fastify.hasRequestDecorator('utility')
|
176 | ```
|
177 |
|
178 | <a name="has-reply-decorator"></a>
|
179 | #### hasReplyDecorator
|
180 | You can check for the presence of a Reply decorator with the `hasReplyDecorator` API:
|
181 | ```js
|
182 | fastify.hasReplyDecorator('utility')
|
183 | ```
|