fastify 4.0.0 → 4.0.3

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/SECURITY.md CHANGED
@@ -1,36 +1,37 @@
1
1
  # Security Policy
2
2
 
3
- This document describes the management of vulnerabilities for the
4
- Fastify project and its official plugins.
3
+ This document describes the management of vulnerabilities for the Fastify
4
+ project and its official plugins.
5
5
 
6
6
  ## Reporting vulnerabilities
7
7
 
8
- Individuals who find potential vulnerabilities in Fastify are invited
9
- to complete a vulnerability report via the dedicated HackerOne page:
8
+ Individuals who find potential vulnerabilities in Fastify are invited to
9
+ complete a vulnerability report via the dedicated HackerOne page:
10
10
  [https://hackerone.com/fastify](https://hackerone.com/fastify).
11
11
 
12
12
  ### Strict measures when reporting vulnerabilities
13
13
 
14
14
  It is of the utmost importance that you read carefully and follow these
15
- guidelines to ensure the ecosystem as a whole isn't disrupted due to
16
- improperly reported vulnerabilities:
15
+ guidelines to ensure the ecosystem as a whole isn't disrupted due to improperly
16
+ reported vulnerabilities:
17
17
 
18
18
  * Avoid creating new "informative" reports on HackerOne. Only create new
19
- HackerOne reports on a vulnerability if you are absolutely sure this
20
- should be tagged as an actual vulnerability. Third-party vendors and
21
- individuals are tracking any new vulnerabilities reported in HackerOne
22
- and will flag them as such for their customers (think about snyk, npm audit, ...).
23
- * HackerOne reports should never be created and triaged by the same person.
24
- If you are creating a HackerOne report for a vulnerability that you found,
25
- or on behalf of someone else, there should always be a 2nd Security Team
26
- member who triages it. If in doubt, invite more Fastify Collaborators to
27
- help triage the validity of the report. In any case, the report should
28
- follow the same process as outlined below of inviting the maintainers
29
- to review and accept the vulnerability.
19
+ HackerOne reports on a vulnerability if you are absolutely sure this should be
20
+ tagged as an actual vulnerability. Third-party vendors and individuals are
21
+ tracking any new vulnerabilities reported in HackerOne and will flag them as
22
+ such for their customers (think about snyk, npm audit, ...).
23
+ * HackerOne reports should never be created and triaged by the same person. If
24
+ you are creating a HackerOne report for a vulnerability that you found, or on
25
+ behalf of someone else, there should always be a 2nd Security Team member who
26
+ triages it. If in doubt, invite more Fastify Collaborators to help triage the
27
+ validity of the report. In any case, the report should follow the same process
28
+ as outlined below of inviting the maintainers to review and accept the
29
+ vulnerability.
30
30
 
31
31
  ### Vulnerabilities found outside this process
32
32
 
33
- ⚠ The Fastify project does not support any reporting outside the HackerOne process.
33
+ ⚠ The Fastify project does not support any reporting outside the HackerOne
34
+ process.
34
35
 
35
36
  ## Handling vulnerability reports
36
37
 
@@ -40,37 +41,40 @@ When a potential vulnerability is reported, the following actions are taken:
40
41
 
41
42
  **Delay:** 4 business days
42
43
 
43
- Within 4 business days, a member of the security team provides a first answer to the
44
- individual who submitted the potential vulnerability. The possible responses
44
+ Within 4 business days, a member of the security team provides a first answer to
45
+ the individual who submitted the potential vulnerability. The possible responses
45
46
  can be:
46
47
 
47
48
  * Acceptance: what was reported is considered as a new vulnerability
48
49
  * Rejection: what was reported is not considered as a new vulnerability
49
- * Need more information: the security team needs more information in order to evaluate what was reported.
50
+ * Need more information: the security team needs more information in order to
51
+ evaluate what was reported.
50
52
 
51
53
  Triaging should include updating issue fields:
52
54
  * Asset - set/create the module affected by the report
53
55
  * Severity - TBD, currently left empty
54
56
 
55
- Reference: [HackerOne: Submitting Reports](https://docs.hackerone.com/hackers/submitting-reports.html)
57
+ Reference: [HackerOne: Submitting
58
+ Reports](https://docs.hackerone.com/hackers/submitting-reports.html)
56
59
 
57
60
  ### Correction follow-up
58
61
 
59
62
  **Delay:** 90 days
60
63
 
61
- When a vulnerability is confirmed, a member of the security team volunteers to follow
62
- up on this report.
64
+ When a vulnerability is confirmed, a member of the security team volunteers to
65
+ follow up on this report.
63
66
 
64
- With the help of the individual who reported the vulnerability, they contact
65
- the maintainers of the vulnerable package to make them aware of the
66
- vulnerability. The maintainers can be invited as participants to the reported issue.
67
+ With the help of the individual who reported the vulnerability, they contact the
68
+ maintainers of the vulnerable package to make them aware of the vulnerability.
69
+ The maintainers can be invited as participants to the reported issue.
67
70
 
68
- With the package maintainer, they define a release date for the publication
69
- of the vulnerability. Ideally, this release date should not happen before
70
- the package has been patched.
71
+ With the package maintainer, they define a release date for the publication of
72
+ the vulnerability. Ideally, this release date should not happen before the
73
+ package has been patched.
71
74
 
72
75
  The report's vulnerable versions upper limit should be set to:
73
- * `*` if there is no fixed version available by the time of publishing the report.
76
+ * `*` if there is no fixed version available by the time of publishing the
77
+ report.
74
78
  * the last vulnerable version. For example: `<=1.2.3` if a fix exists in `1.2.4`
75
79
 
76
80
  ### Publication
@@ -79,34 +83,41 @@ The report's vulnerable versions upper limit should be set to:
79
83
 
80
84
  Within 90 days after the triage date, the vulnerability must be made public.
81
85
 
82
- **Severity**: Vulnerability severity is assessed using [CVSS v.3](https://www.first.org/cvss/user-guide).
83
- More information can be found on [HackerOne documentation](https://docs.hackerone.com/hackers/severity.html)
86
+ **Severity**: Vulnerability severity is assessed using [CVSS
87
+ v.3](https://www.first.org/cvss/user-guide). More information can be found on
88
+ [HackerOne documentation](https://docs.hackerone.com/hackers/severity.html)
84
89
 
85
90
  If the package maintainer is actively developing a patch, an additional delay
86
91
  can be added with the approval of the security team and the individual who
87
- reported the vulnerability.
92
+ reported the vulnerability.
88
93
 
89
94
  At this point, a CVE should be requested through the HackerOne platform through
90
95
  the UI, which should include the Report ID and a summary.
91
96
 
92
97
  Within HackerOne, this is handled through a "public disclosure request".
93
98
 
94
- Reference: [HackerOne: Disclosure](https://docs.hackerone.com/hackers/disclosure.html)
99
+ Reference: [HackerOne:
100
+ Disclosure](https://docs.hackerone.com/hackers/disclosure.html)
95
101
 
96
102
  ## The Fastify Security team
97
103
 
98
- The core team is responsible for the management of HackerOne program and this policy and process.
104
+ The core team is responsible for the management of HackerOne program and this
105
+ policy and process.
99
106
 
100
- Members of this team are expected to keep all information that they have privileged access to by being
101
- on the team completely private to the team. This includes agreeing to not notify anyone outside the
102
- team of issues that have not yet been disclosed publicly, including the existence of issues,
103
- expectations of upcoming releases, and patching of any issues other than in the process of their work
104
- as a member of the Fastify Core team.
107
+ Members of this team are expected to keep all information that they have
108
+ privileged access to by being on the team completely private to the team. This
109
+ includes agreeing to not notify anyone outside the team of issues that have not
110
+ yet been disclosed publicly, including the existence of issues, expectations of
111
+ upcoming releases, and patching of any issues other than in the process of their
112
+ work as a member of the Fastify Core team.
105
113
 
106
114
  ### Members
107
115
 
108
- * [__Matteo Collina__](https://github.com/mcollina), <https://twitter.com/matteocollina>, <https://www.npmjs.com/~matteo.collina>
109
- * [__Tomas Della Vedova__](https://github.com/delvedor), <https://twitter.com/delvedor>, <https://www.npmjs.com/~delvedor>
116
+ * [__Matteo Collina__](https://github.com/mcollina),
117
+ <https://twitter.com/matteocollina>, <https://www.npmjs.com/~matteo.collina>
118
+ * [__Tomas Della Vedova__](https://github.com/delvedor),
119
+ <https://twitter.com/delvedor>, <https://www.npmjs.com/~delvedor>
110
120
  * [__Vincent Le Goff__](https://github.com/zekth)
111
121
  * [__KaKa Ng__](https://github.com/climba03003)
112
- * [__James Sumners__](https://github.com/jsumners), <https://twitter.com/jsumners79>, <https://www.npmjs.com/~jsumners>
122
+ * [__James Sumners__](https://github.com/jsumners),
123
+ <https://twitter.com/jsumners79>, <https://www.npmjs.com/~jsumners>
@@ -1,10 +1,11 @@
1
+ /* istanbul ignore file */
1
2
  'use strict'
2
3
 
3
4
  const FJS = require('fast-json-stringify')
4
5
  const path = require('path')
5
6
  const fs = require('fs')
6
7
 
7
- const debugCompiled = FJS({
8
+ const code = FJS({
8
9
  type: 'object',
9
10
  properties: {
10
11
  statusCode: { type: 'number' },
@@ -12,16 +13,20 @@ const debugCompiled = FJS({
12
13
  error: { type: 'string' },
13
14
  message: { type: 'string' }
14
15
  }
15
- }, { debugMode: true })
16
+ }, { mode: 'standalone' })
16
17
 
17
18
  const file = path.join(__dirname, '..', 'lib', 'error-serializer.js')
18
- const rawString = debugCompiled.toString()
19
19
 
20
20
  const moduleCode = `// This file is autogenerated by build/build-error-serializer.js, do not edit
21
21
  /* istanbul ignore file */
22
- module.exports = $main
23
- ${rawString.slice(5)}
22
+ ${code}
24
23
  `
25
24
 
26
- fs.writeFileSync(file, moduleCode)
27
- console.log(`Saved ${file} file successfully`)
25
+ if (require.main === module) {
26
+ fs.writeFileSync(file, moduleCode)
27
+ console.log(`Saved ${file} file successfully`)
28
+ } else {
29
+ module.exports = {
30
+ code: moduleCode
31
+ }
32
+ }
@@ -53,6 +53,8 @@ npm run bench
53
53
 
54
54
  ### Run different examples
55
55
 
56
+ <!-- markdownlint-disable -->
56
57
  ```sh
57
58
  branchcmp --rounds 2 -s "node ./node_modules/concurrently -k -s first \"node ./examples/asyncawait.js\" \"node ./node_modules/autocannon -c 100 -d 5 -p 10 localhost:3000/\""
58
59
  ```
60
+ <!-- markdownlint-enable -->
@@ -5,15 +5,16 @@
5
5
  ## Introduction
6
6
 
7
7
  Fastify provides several [hooks](../Reference/Hooks.md) useful for a variety of
8
- situations. One of them is the [`onReady`](../Reference/Hooks.md#onready) hook, which is
9
- useful for executing tasks *right before* the server starts accepting new
10
- requests. There isn't, though, a direct mechanism to handle scenarios in which
11
- you'd like the server to start accepting **specific** requests and denying all
12
- others, at least up to some point.
13
-
14
- Say, for instance, your server needs to authenticate with an OAuth provider
15
- to start serving requests. To do that it'd need to engage in the
16
- [OAuth Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow),
8
+ situations. One of them is the [`onReady`](../Reference/Hooks.md#onready) hook,
9
+ which is useful for executing tasks *right before* the server starts accepting
10
+ new requests. There isn't, though, a direct mechanism to handle scenarios in
11
+ which you'd like the server to start accepting **specific** requests and denying
12
+ all others, at least up to some point.
13
+
14
+ Say, for instance, your server needs to authenticate with an OAuth provider to
15
+ start serving requests. To do that it'd need to engage in the [OAuth
16
+ Authorization Code
17
+ Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow),
17
18
  which would require it to listen to two requests from the authentication
18
19
  provider:
19
20
 
@@ -31,14 +32,13 @@ rolling asap!
31
32
 
32
33
  ### Overview
33
34
 
34
- The proposed solution is one of many possible ways of dealing with this
35
- scenario and many similar to it. It relies solely on Fastify, so no
36
- fancy infrastructure tricks or third-party libraries will be necessary.
35
+ The proposed solution is one of many possible ways of dealing with this scenario
36
+ and many similar to it. It relies solely on Fastify, so no fancy infrastructure
37
+ tricks or third-party libraries will be necessary.
37
38
 
38
- To simplify things we won't be dealing with a precise OAuth flow but,
39
- instead, simulate a scenario in which some key is needed to serve
40
- a request and that key can only be retrieved in runtime by authenticating with
41
- an external provider.
39
+ To simplify things we won't be dealing with a precise OAuth flow but, instead,
40
+ simulate a scenario in which some key is needed to serve a request and that key
41
+ can only be retrieved in runtime by authenticating with an external provider.
42
42
 
43
43
  The main goal here is to deny requests that would otherwise fail **as early as
44
44
  possible** and with some **meaningful context**. That's both useful for the
@@ -97,7 +97,7 @@ server.get('/v1*', async function (request, reply) {
97
97
  error,
98
98
  message: 'Failed at fetching sensitive data from provider',
99
99
  })
100
-
100
+
101
101
  reply.statusCode = 500
102
102
  return { customer: null, error: true }
103
103
  }
@@ -122,13 +122,13 @@ server.listen({ port: '1234' }, () => {
122
122
 
123
123
  Our code is simply setting up a Fastify server with a few routes:
124
124
 
125
- - a `/ping` route that specifies whether the service is ready or
126
- not to serve requests by checking if the `magicKey` has been set up
127
- - a `/webhook` endpoint for our provider to reach back to us when
128
- they're ready to share the `magicKey`. The `magicKey` is, then, saved into the
129
- previously set decorator on the `fastify` object
130
- - a catchall `/v1*` route to simulate what would have been
131
- customer-initiated requests. These requests rely on us having a valid `magicKey`
125
+ - a `/ping` route that specifies whether the service is ready or not to serve
126
+ requests by checking if the `magicKey` has been set up
127
+ - a `/webhook` endpoint for our provider to reach back to us when they're ready
128
+ to share the `magicKey`. The `magicKey` is, then, saved into the previously set
129
+ decorator on the `fastify` object
130
+ - a catchall `/v1*` route to simulate what would have been customer-initiated
131
+ requests. These requests rely on us having a valid `magicKey`
132
132
 
133
133
  The `provider.js` file, simulating actions of an external provider, is as
134
134
  follows:
@@ -166,11 +166,11 @@ exports.fetchSensitiveData = async (key) => {
166
166
  // Simulate processing delay
167
167
  await delay(700)
168
168
  const data = { sensitive: true }
169
-
169
+
170
170
  if (key === MAGIC_KEY) {
171
171
  return data
172
172
  }
173
-
173
+
174
174
  throw new Error('Invalid key')
175
175
  }
176
176
  ```
@@ -184,16 +184,16 @@ our `magicKey` set up. Until we receive the webhook request from our external
184
184
  provider (in this example we're simulating a 5 second delay) all our requests
185
185
  under the `/v1*` path (customer requests) will fail. Worse than that: they'll
186
186
  fail after we've reached out to our provider with an invalid key and got an
187
- error from them. That wasted time and resources for us and our
188
- customers. Depending on the kind of application we're running and on the request
189
- rate we're expecting this delay is not acceptable or, at least, very annoying.
187
+ error from them. That wasted time and resources for us and our customers.
188
+ Depending on the kind of application we're running and on the request rate we're
189
+ expecting this delay is not acceptable or, at least, very annoying.
190
190
 
191
191
  Of course, that could be simply mitigated by checking whether or not the
192
192
  `magicKey` has been set up before hitting the provider in the `/v1*` handler.
193
193
  Sure, but that would lead to bloat in the code. And imagine we have dozens of
194
- different routes, with different controllers, that require that key. Should
195
- we repeatedly add that check to all of them? That's error-prone and there are
196
- more elegant solutions.
194
+ different routes, with different controllers, that require that key. Should we
195
+ repeatedly add that check to all of them? That's error-prone and there are more
196
+ elegant solutions.
197
197
 
198
198
  What we'll do to improve this setup overall is create a
199
199
  [`Plugin`](../Reference/Plugins.md) that'll be solely responsible for making
@@ -280,11 +280,11 @@ exports.fetchSensitiveData = async (key) => {
280
280
  // Simulate processing delay
281
281
  await delay(700)
282
282
  const data = { sensitive: true }
283
-
283
+
284
284
  if (key === MAGIC_KEY) {
285
285
  return data
286
286
  }
287
-
287
+
288
288
  throw new Error('Invalid key')
289
289
  }
290
290
  ```
@@ -381,9 +381,9 @@ There is a very specific change on the previously existing files that is worth
381
381
  mentioning: Beforehand we were using the `server.listen` callback to start the
382
382
  authentication process with the external provider and we were decorating the
383
383
  `server` object right before initializing the server. That was bloating our
384
- server initialization setup with unnecessary code and didn't have much to
385
- do with starting the Fastify server. It was a business logic that didn't have
386
- its specific place in the code base.
384
+ server initialization setup with unnecessary code and didn't have much to do
385
+ with starting the Fastify server. It was a business logic that didn't have its
386
+ specific place in the code base.
387
387
 
388
388
  Now we've implemented the `delayIncomingRequests` plugin in the
389
389
  `delay-incoming-requests.js` file. That's, in truth, a module split into two
@@ -399,11 +399,11 @@ asap and store the `magicKey` somewhere available to all our handlers.
399
399
  fastify.server.on('listening', doMagic)
400
400
  ```
401
401
 
402
- As soon as the server starts listening (very similar behavior to adding a
403
- piece of code to the `server.listen`'s callback function) a `listening` event
404
- is emitted (for more info refer to https://nodejs.org/api/net.html#event-listening).
405
- We use that to reach out to our provider as soon as possible, with the `doMagic`
406
- function.
402
+ As soon as the server starts listening (very similar behavior to adding a piece
403
+ of code to the `server.listen`'s callback function) a `listening` event is
404
+ emitted (for more info refer to
405
+ https://nodejs.org/api/net.html#event-listening). We use that to reach out to
406
+ our provider as soon as possible, with the `doMagic` function.
407
407
 
408
408
  ```js
409
409
  fastify.decorate('magicKey', null)
@@ -414,10 +414,10 @@ a placeholder, waiting for the valid value to be retrieved.
414
414
 
415
415
  ##### delay
416
416
 
417
- `delay` is not a plugin itself. It's actually a plugin *factory*. It expects
418
- a Fastify plugin with `routes` and exports the actual plugin that'll handle
419
- enveloping those routes with an `onRequest` hook that will make sure no
420
- requests are handled until we're ready for them.
417
+ `delay` is not a plugin itself. It's actually a plugin *factory*. It expects a
418
+ Fastify plugin with `routes` and exports the actual plugin that'll handle
419
+ enveloping those routes with an `onRequest` hook that will make sure no requests
420
+ are handled until we're ready for them.
421
421
 
422
422
  ```js
423
423
  const delay = (routes) =>
@@ -441,33 +441,34 @@ const delay = (routes) =>
441
441
  }
442
442
  ```
443
443
 
444
- Instead of updating every single controller that might use the
445
- `magicKey`, we simply make sure that no route that's related to customer requests
446
- will be served until we have everything ready. And there's more: we fail
447
- **FAST** and have the possibility of giving the customer meaningful information,
448
- like how long they should wait before retrying the request. Going even further,
449
- by issuing a
450
- [`503` status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503)
451
- we're signaling to our infrastructure components (namely load balancers) we're
452
- still not ready to take incoming requests and they should redirect traffic
453
- to other instances, if available, besides in how long we estimate that will be
454
- solved. All of that in a few simple lines!
444
+ Instead of updating every single controller that might use the `magicKey`, we
445
+ simply make sure that no route that's related to customer requests will be
446
+ served until we have everything ready. And there's more: we fail **FAST** and
447
+ have the possibility of giving the customer meaningful information, like how
448
+ long they should wait before retrying the request. Going even further, by
449
+ issuing a [`503` status
450
+ code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) we're
451
+ signaling to our infrastructure components (namely load balancers) we're still
452
+ not ready to take incoming requests and they should redirect traffic to other
453
+ instances, if available, besides in how long we estimate that will be solved.
454
+ All of that in a few simple lines!
455
455
 
456
456
  It's noteworthy that we didn't use the `fastify-plugin` wrapper in the `delay`
457
457
  factory. That's because we wanted the `onRequest` hook to only be set within
458
- that specific scope and not to the scope that called it (in our case, the
459
- main `server` object defined in `index.js`). `fastify-plugin` sets the
460
- `skip-override` hidden property, which has a practical effect of making
461
- whatever changes we make to our `fastify` object available to the upper scope.
462
- That's also why we used it with the `customerRoutes` plugin: we wanted those
463
- routes to be available to its calling scope, the `delay` plugin. For more info
464
- on that subject refer to [Plugins](../Reference/Plugins.md#handle-the-scope).
465
-
466
- Let's see how that behaves in action. If we fired our server up with
467
- `node index.js` and made a few requests to test things out. These were the logs
468
- we'd see (some bloat was removed to ease things up):
469
-
470
- ```
458
+ that specific scope and not to the scope that called it (in our case, the main
459
+ `server` object defined in `index.js`). `fastify-plugin` sets the
460
+ `skip-override` hidden property, which has a practical effect of making whatever
461
+ changes we make to our `fastify` object available to the upper scope. That's
462
+ also why we used it with the `customerRoutes` plugin: we wanted those routes to
463
+ be available to its calling scope, the `delay` plugin. For more info on that
464
+ subject refer to [Plugins](../Reference/Plugins.md#handle-the-scope).
465
+
466
+ Let's see how that behaves in action. If we fired our server up with `node
467
+ index.js` and made a few requests to test things out. These were the logs we'd
468
+ see (some bloat was removed to ease things up):
469
+
470
+ <!-- markdownlint-disable -->
471
+ ```sh
471
472
  {"time":1650063793316,"msg":"Doing magic!"}
472
473
  {"time":1650063793316,"msg":"Server listening at http://127.0.0.1:1234"}
473
474
  {"time":1650063795030,"reqId":"req-1","req":{"method":"GET","url":"/v1","hostname":"localhost:1234","remoteAddress":"127.0.0.1","remotePort":51928},"msg":"incoming request"}
@@ -480,10 +481,11 @@ we'd see (some bloat was removed to ease things up):
480
481
  {"time":1650063799858,"reqId":"req-4","req":{"method":"GET","url":"/v1","hostname":"localhost:1234","remoteAddress":"127.0.0.1","remotePort":51934},"msg":"incoming request"}
481
482
  {"time":1650063800561,"reqId":"req-4","res":{"statusCode":200},"responseTime":702.4662979990244,"msg":"request completed"}
482
483
  ```
484
+ <!-- markdownlint-enable -->
483
485
 
484
486
  Let's focus on a few parts:
485
487
 
486
- ```
488
+ ```sh
487
489
  {"time":1650063793316,"msg":"Doing magic!"}
488
490
  {"time":1650063793316,"msg":"Server listening at http://127.0.0.1:1234"}
489
491
  ```
@@ -494,18 +496,20 @@ couldn't do that before the server was ready to receive connections).
494
496
 
495
497
  While the server is still not ready, a few requests are attempted:
496
498
 
497
- ```
499
+ <!-- markdownlint-disable -->
500
+ ```sh
498
501
  {"time":1650063795030,"reqId":"req-1","req":{"method":"GET","url":"/v1","hostname":"localhost:1234","remoteAddress":"127.0.0.1","remotePort":51928},"msg":"incoming request"}
499
502
  {"time":1650063795033,"reqId":"req-1","res":{"statusCode":503},"responseTime":2.5721680000424385,"msg":"request completed"}
500
503
  {"time":1650063796248,"reqId":"req-2","req":{"method":"GET","url":"/ping","hostname":"localhost:1234","remoteAddress":"127.0.0.1","remotePort":51930},"msg":"incoming request"}
501
504
  {"time":1650063796248,"reqId":"req-2","res":{"statusCode":200},"responseTime":0.4802369996905327,"msg":"request completed"}
502
505
  ```
506
+ <!-- markdownlint-enable -->
503
507
 
504
508
  The first one (`req-1`) was a `GET /v1`, that failed (**FAST** - `responseTime`
505
509
  is in `ms`) with our `503` status code and the meaningful information in the
506
510
  response. Below is the response for that request:
507
511
 
508
- ```
512
+ ```sh
509
513
  HTTP/1.1 503 Service Unavailable
510
514
  Connection: keep-alive
511
515
  Content-Length: 31
@@ -524,12 +528,12 @@ Then we attempt a new request (`req-2`), which was a `GET /ping`. As expected,
524
528
  since that was not one of the requests we asked our plugin to filter, it
525
529
  succeeded. That could also be used as means of informing an interested party
526
530
  whether or not we were ready to serve requests (although `/ping` is more
527
- commonly associated with _liveness_ checks and that would be the responsibility
528
- of a _readiness_ check -- the curious reader can get more info on these terms
529
- [here](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes)) with the `ready` field.
530
- Below is the response for that request:
531
+ commonly associated with *liveness* checks and that would be the responsibility
532
+ of a *readiness* check -- the curious reader can get more info on these terms
533
+ [here](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes))
534
+ with the `ready` field. Below is the response for that request:
531
535
 
532
- ```
536
+ ```sh
533
537
  HTTP/1.1 200 OK
534
538
  Connection: keep-alive
535
539
  Content-Length: 29
@@ -545,26 +549,30 @@ Keep-Alive: timeout=5
545
549
 
546
550
  After that there were more interesting log messages:
547
551
 
548
- ```
552
+ <!-- markdownlint-disable -->
553
+ ```sh
549
554
  {"time":1650063798377,"reqId":"req-3","req":{"method":"POST","url":"/webhook","hostname":"localhost:1234","remoteAddress":"127.0.0.1","remotePort":51932},"msg":"incoming request"}
550
555
  {"time":1650063798379,"reqId":"req-3","msg":"Ready for customer requests!"}
551
556
  {"time":1650063798379,"reqId":"req-3","res":{"statusCode":200},"responseTime":1.3567829988896847,"msg":"request completed"}
552
557
  ```
558
+ <!-- markdownlint-enable -->
553
559
 
554
560
  This time it was our simulated external provider hitting us to let us know
555
561
  authentication had gone well and telling us what our `magicKey` was. We saved
556
562
  that into our `magicKey` decorator and celebrated with a log message saying we
557
563
  were now ready for customers to hit us!
558
564
 
559
- ```
565
+ <!-- markdownlint-disable -->
566
+ ```sh
560
567
  {"time":1650063799858,"reqId":"req-4","req":{"method":"GET","url":"/v1","hostname":"localhost:1234","remoteAddress":"127.0.0.1","remotePort":51934},"msg":"incoming request"}
561
568
  {"time":1650063800561,"reqId":"req-4","res":{"statusCode":200},"responseTime":702.4662979990244,"msg":"request completed"}
562
569
  ```
570
+ <!-- markdownlint-enable -->
563
571
 
564
572
  Finally, a final `GET /v1` request was made and, this time, it succeeded. Its
565
573
  response was the following:
566
574
 
567
- ```
575
+ ```sh
568
576
  HTTP/1.1 200 OK
569
577
  Connection: keep-alive
570
578
  Content-Length: 31
@@ -580,18 +588,18 @@ Keep-Alive: timeout=5
580
588
 
581
589
  ## Conclusion
582
590
 
583
- Specifics of the implementation will vary
584
- from one problem to another, but the main goal of this guide was to show a very
585
- specific use case of an issue that could be solved within Fastify's ecosystem.
591
+ Specifics of the implementation will vary from one problem to another, but the
592
+ main goal of this guide was to show a very specific use case of an issue that
593
+ could be solved within Fastify's ecosystem.
586
594
 
587
595
  This guide is a tutorial on the use of plugins, decorators, and hooks to solve
588
596
  the problem of delaying serving specific requests on our application. It's not
589
597
  production-ready, as it keeps local state (the `magicKey`) and it's not
590
- horizontally scalable (we don't want to flood our provider, right?). One way
591
- of improving it would be storing the `magicKey` somewhere else (perhaps a
592
- cache database?).
598
+ horizontally scalable (we don't want to flood our provider, right?). One way of
599
+ improving it would be storing the `magicKey` somewhere else (perhaps a cache
600
+ database?).
593
601
 
594
602
  The keywords here were [Decorators](../Reference/Decorators.md),
595
- [Hooks](../Reference/Hooks.md), and [Plugins](../Reference/Plugins.md). Combining
596
- what Fastify has to offer can lead to very ingenious and creative solutions to a
597
- wide variety of problems. Let's be creative! :)
603
+ [Hooks](../Reference/Hooks.md), and [Plugins](../Reference/Plugins.md).
604
+ Combining what Fastify has to offer can lead to very ingenious and creative
605
+ solutions to a wide variety of problems. Let's be creative! :)