fastify 4.1.0 → 4.3.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.
Files changed (56) hide show
  1. package/README.md +13 -14
  2. package/docs/Guides/Database.md +2 -2
  3. package/docs/Guides/Delay-Accepting-Requests.md +1 -1
  4. package/docs/Guides/Ecosystem.md +31 -16
  5. package/docs/Guides/Migration-Guide-V4.md +69 -1
  6. package/docs/Guides/Plugins-Guide.md +5 -0
  7. package/docs/Guides/Serverless.md +23 -10
  8. package/docs/Reference/HTTP2.md +1 -3
  9. package/docs/Reference/Hooks.md +52 -0
  10. package/docs/Reference/Plugins.md +1 -1
  11. package/docs/Reference/Reply.md +176 -0
  12. package/docs/Reference/Request.md +171 -0
  13. package/docs/Reference/Type-Providers.md +1 -15
  14. package/docs/Reference/TypeScript.md +65 -28
  15. package/docs/Reference/Validation-and-Serialization.md +11 -0
  16. package/docs/index.md +1 -1
  17. package/fastify.d.ts +3 -3
  18. package/fastify.js +2 -2
  19. package/integration/server.js +27 -0
  20. package/integration/test.sh +23 -0
  21. package/lib/contentTypeParser.js +10 -2
  22. package/lib/context.js +14 -2
  23. package/lib/error-serializer.js +24 -27
  24. package/lib/errors.js +8 -0
  25. package/lib/handleRequest.js +1 -1
  26. package/lib/reply.js +101 -24
  27. package/lib/request.js +97 -1
  28. package/lib/route.js +41 -29
  29. package/lib/symbols.js +17 -10
  30. package/lib/validation.js +2 -0
  31. package/package.json +9 -9
  32. package/test/build/error-serializer.test.js +3 -1
  33. package/test/content-parser.test.js +15 -0
  34. package/test/hooks.test.js +21 -0
  35. package/test/internals/reply-serialize.test.js +583 -0
  36. package/test/internals/request-validate.test.js +1269 -0
  37. package/test/internals/request.test.js +11 -2
  38. package/test/pretty-print.test.js +3 -3
  39. package/test/reply-error.test.js +1 -1
  40. package/test/request-error.test.js +44 -1
  41. package/test/schema-feature.test.js +2 -2
  42. package/test/schema-validation.test.js +71 -0
  43. package/test/types/fastify.test-d.ts +24 -2
  44. package/test/types/hooks.test-d.ts +1 -2
  45. package/test/types/import.ts +1 -1
  46. package/test/types/instance.test-d.ts +4 -1
  47. package/test/types/request.test-d.ts +8 -4
  48. package/test/types/type-provider.test-d.ts +87 -8
  49. package/test/validation-error-handling.test.js +38 -1
  50. package/types/hooks.d.ts +19 -39
  51. package/types/instance.d.ts +78 -130
  52. package/types/reply.d.ts +5 -0
  53. package/types/request.d.ts +16 -3
  54. package/types/route.d.ts +25 -33
  55. package/types/schema.d.ts +4 -1
  56. package/types/type-provider.d.ts +19 -11
package/README.md CHANGED
@@ -38,18 +38,18 @@ resources of your server, knowing that you are serving the highest number of
38
38
  requests as possible, without sacrificing security validations and handy
39
39
  development?
40
40
 
41
- - [Quick start](./README.md#quick-start)
42
- - [Install](./README.md#install)
43
- - [Example](./README.md#example)
44
- - [Fastify v1.x and v2.x](./README.md#fastify-v1x-and-v2x)
45
- - [Core features](./README.md#core-features)
46
- - [Benchmarks](./README.md#benchmarks)
47
- - [Documentation](./README.md#documentation)
48
- - [Ecosystem](./README.md#ecosystem)
49
- - [Support](./README.md#support)
50
- - [Team](./README.md#team)
51
- - [Hosted by](./README.md#hosted-by)
52
- - [License](./README.md#license)
41
+ - [Quick start](#quick-start)
42
+ - [Install](#install)
43
+ - [Example](#example)
44
+ - [Fastify v1.x and v2.x](#fastify-v1x-and-v2x)
45
+ - [Core features](#core-features)
46
+ - [Benchmarks](#benchmarks)
47
+ - [Documentation](#documentation)
48
+ - [Ecosystem](#ecosystem)
49
+ - [Support](#support)
50
+ - [Team](#team)
51
+ - [Hosted by](#hosted-by)
52
+ - [License](#license)
53
53
 
54
54
  Enter Fastify. Fastify is a web framework highly focused on providing the best
55
55
  developer experience with the least overhead and a powerful plugin architecture.
@@ -99,8 +99,7 @@ generate functionality of [Fastify CLI](https://github.com/fastify/fastify-cli).
99
99
 
100
100
  ### Install
101
101
 
102
- If installing in an existing project, then Fastify can be installed into the
103
- project as a dependency:
102
+ To install Fastify in an existing project as a dependency:
104
103
 
105
104
  Install with npm:
106
105
  ```sh
@@ -204,7 +204,7 @@ function knexPlugin(fastify, options, done) {
204
204
  done()
205
205
  }
206
206
 
207
- export default fp(plugin, { name: 'fastify-knex-example' })
207
+ export default fp(knexPlugin, { name: 'fastify-knex-example' })
208
208
  ```
209
209
 
210
210
  ### Writing a plugin for a database engine
@@ -213,7 +213,7 @@ In this example, we will create a basic Fastify MySQL plugin from scratch (it is
213
213
  a stripped-down example, please use the official plugin in production).
214
214
 
215
215
  ```javascript
216
- const fp = require('fp')
216
+ const fp = require('fastify-plugin')
217
217
  const mysql = require('mysql2/promise')
218
218
 
219
219
  function fastifyMysql(fastify, options, done) {
@@ -48,7 +48,7 @@ server (fewer resources allocated to a bound-to-fail task) and for the client
48
48
  That will be achieved by wrapping into a custom plugin two main features:
49
49
 
50
50
  1. the mechanism for authenticating with the provider
51
- [decorating](../Referece/Decorators.md) the `fastify` object with the
51
+ [decorating](../Reference/Decorators.md) the `fastify` object with the
52
52
  authentication key (`magicKey` from here onwards)
53
53
  1. the mechanism for denying requests that would, otherwise, fail
54
54
 
@@ -132,9 +132,15 @@ section.
132
132
  sampling process metrics.
133
133
  - [`@dnlup/fastify-traps`](https://github.com/dnlup/fastify-traps) A plugin to
134
134
  close the server gracefully on `SIGINT` and `SIGTERM` signals.
135
+ - [`@eropple/fastify-openapi3`](https://github.com/eropple/fastify-openapi3) Provides
136
+ easy, developer-friendly OpenAPI 3.1 specs + doc explorer based on your routes.
135
137
  - [`@gquittet/graceful-server`](https://github.com/gquittet/graceful-server)
136
138
  Tiny (~5k), Fast, KISS, and dependency-free Node.JS library to make your
137
139
  Fastify API graceful.
140
+ - [`@h4ad/serverless-adapter`](https://github.com/H4ad/serverless-adapter)
141
+ Run REST APIs and other web applications using your existing Node.js
142
+ application framework (Express, Koa, Hapi and Fastify), on top of AWS Lambda,
143
+ Huawei and many other clouds.
138
144
  - [`@immobiliarelabs/fastify-metrics`](https://github.com/immobiliare/fastify-metrics)
139
145
  Minimalistic and opinionated plugin that collects usage/process metrics and
140
146
  dispatches to [statsd](https://github.com/statsd/statsd).
@@ -145,12 +151,12 @@ section.
145
151
  A plugin to close the server gracefully
146
152
  - [`@mgcrea/fastify-request-logger`](https://github.com/mgcrea/fastify-request-logger)
147
153
  A plugin to enable compact request logging for Fastify
154
+ - [`@mgcrea/fastify-session`](https://github.com/mgcrea/fastify-session) Session
155
+ plugin for Fastify that supports both stateless and stateful sessions
148
156
  - [`@mgcrea/fastify-session-redis-store`](https://github.com/mgcrea/fastify-session-redis-store)
149
157
  Redis store for @mgcrea/fastify-session using ioredis
150
158
  - [`@mgcrea/fastify-session-sodium-crypto`](https://github.com/mgcrea/fastify-session-sodium-crypto)
151
159
  Fast sodium-based crypto for @mgcrea/fastify-session
152
- - [`@mgcrea/fastify-session`](https://github.com/mgcrea/fastify-session) Session
153
- plugin for Fastify that supports both stateless and stateful sessions
154
160
  - [`@mgcrea/pino-pretty-compact`](https://github.com/mgcrea/pino-pretty-compact)
155
161
  A custom compact pino-base prettifier
156
162
  - [`@trubavuong/fastify-seaweedfs`](https://github.com/trubavuong/fastify-seaweedfs)
@@ -163,6 +169,10 @@ section.
163
169
  - [`cls-rtracer`](https://github.com/puzpuzpuz/cls-rtracer) Fastify middleware
164
170
  for CLS-based request ID generation. An out-of-the-box solution for adding
165
171
  request IDs into your logs.
172
+ - [`electron-server`](https://github.com/anonrig/electron-server) A plugin for
173
+ using Fastify without the need of consuming a port on Electron apps.
174
+ - [`fast-water`](https://github.com/tswayne/fast-water) A Fastify plugin for
175
+ waterline. Decorates Fastify with waterline models.
166
176
  - [`fastify-405`](https://github.com/Eomm/fastify-405) Fastify plugin that adds
167
177
  405 HTTP status to your routes
168
178
  - [`fastify-allow`](https://github.com/mattbishop/fastify-allow) Fastify plugin
@@ -281,13 +291,13 @@ section.
281
291
  good Fastify sessions plugin focused on speed.
282
292
  - [`fastify-google-cloud-storage`](https://github.com/carlozamagni/fastify-google-cloud-storage)
283
293
  Fastify plugin that exposes a GCP Cloud Storage client instance.
294
+ - [`fastify-graceful-shutdown`](https://github.com/hemerajs/fastify-graceful-shutdown)
295
+ Shutdown Fastify gracefully and asynchronously.
284
296
  - [`fastify-grant`](https://github.com/simov/fastify-grant)
285
297
  Authentication/Authorization plugin for Fastify that supports 200+ OAuth
286
298
  Providers.
287
299
  - [`fastify-guard`](https://github.com/hsynlms/fastify-guard) A Fastify plugin
288
300
  that protects endpoints by checking authenticated user roles and/or scopes.
289
- - [`fastify-graceful-shutdown`](https://github.com/hemerajs/fastify-graceful-shutdown)
290
- Shutdown Fastify gracefully and asynchronously.
291
301
  - [`fastify-hasura`](https://github.com/ManUtopiK/fastify-hasura) A Fastify
292
302
  plugin to have fun with [Hasura](https://github.com/hasura/graphql-engine).
293
303
  - [`fastify-healthcheck`](https://github.com/smartiniOnGitHub/fastify-healthcheck)
@@ -295,20 +305,19 @@ section.
295
305
  - [`fastify-hemera`](https://github.com/hemerajs/fastify-hemera) Fastify Hemera
296
306
  plugin, for writing reliable & fault-tolerant microservices with
297
307
  [nats.io](https://nats.io/).
308
+ - [`fastify-http-client`](https://github.com/kenuyx/fastify-http-client) Plugin
309
+ to send HTTP(s) requests. Built upon [urllib](https://github.com/node-modules/urllib).
298
310
  - [`fastify-http-context`](https://github.com/thorough-developer/fastify-http-context)
299
311
  Fastify plugin for "simulating" a thread of execution to allow for true HTTP
300
312
  context to take place per API call within the Fastify lifecycle of calls.
313
+ - [`fastify-http-errors-enhanced`](https://github.com/ShogunPanda/fastify-http-errors-enhanced)
314
+ An error handling plugin for Fastify that uses enhanced HTTP errors.
301
315
  - [`fastify-http2https`](https://github.com/lolo32/fastify-http2https) Redirect
302
316
  HTTP requests to HTTPS, both using the same port number, or different response
303
317
  on HTTP and HTTPS.
304
- - [`fastify-http-client`](https://github.com/kenuyx/fastify-http-client) Plugin
305
- to send HTTP(s) requests. Built upon
306
- [urllib](https://github.com/node-modules/urllib).
307
- - [`fastify-http-errors-enhanced`](https://github.com/ShogunPanda/fastify-http-errors-enhanced)
308
- An error handling plugin for Fastify that uses enhanced HTTP errors.
309
318
  - [`fastify-https-redirect`](https://github.com/tomsvogel/fastify-https-redirect)
310
319
  Fastify plugin for auto-redirect from HTTP to HTTPS.
311
- - [`fatify-impressions`](https://github.com/manju4ever/fastify-impressions)
320
+ - [`fastify-impressions`](https://github.com/manju4ever/fastify-impressions)
312
321
  Fastify plugin to track impressions of all the routes.
313
322
  - [`fastify-influxdb`](https://github.com/alex-ppg/fastify-influxdb) Fastify
314
323
  InfluxDB plugin connecting to an InfluxDB instance via the Influx default
@@ -327,6 +336,8 @@ section.
327
336
  Kubernetes client plugin.
328
337
  - [`fastify-language-parser`](https://github.com/lependu/fastify-language-parser)
329
338
  Fastify plugin to parse request language.
339
+ - [`fastify-lcache`](https://github.com/denbon05/fastify-lcache)
340
+ Lightweight cache plugin
330
341
  - [`fastify-loader`](https://github.com/TheNoim/fastify-loader) Load routes from
331
342
  a directory and inject the Fastify instance in each file.
332
343
  - [`fastify-lured`](https://github.com/lependu/fastify-lured) Plugin to load lua
@@ -400,10 +411,10 @@ section.
400
411
  - [`fastify-orientdb`](https://github.com/mahmed8003/fastify-orientdb) Fastify
401
412
  OrientDB connection plugin, with which you can share the OrientDB connection
402
413
  across every part of your server.
403
- - [`fastify-piscina`](https://github.com/piscinajs/fastify-piscina) A worker
404
- thread pool plugin using [Piscina](https://github.com/piscinajs/piscina).
405
414
  - [`fastify-peekaboo`](https://github.com/simone-sanfratello/fastify-peekaboo)
406
415
  Fastify plugin for memoize responses by expressive settings.
416
+ - [`fastify-piscina`](https://github.com/piscinajs/fastify-piscina) A worker
417
+ thread pool plugin using [Piscina](https://github.com/piscinajs/piscina).
407
418
  - [`fastify-polyglot`](https://github.com/heply/fastify-polyglot) A plugin to
408
419
  handle i18n using
409
420
  [node-polyglot](https://www.npmjs.com/package/node-polyglot).
@@ -436,10 +447,10 @@ section.
436
447
  - [`fastify-register-routes`](https://github.com/israeleriston/fastify-register-routes)
437
448
  Plugin to automatically load routes from a specified path and optionally limit
438
449
  loaded file names by a regular expression.
439
- - [`fastify-response-time`](https://github.com/lolo32/fastify-response-time) Add
440
- `X-Response-Time` header at each request for Fastify, in milliseconds.
441
450
  - [`fastify-response-caching`](https://github.com/codeaholicguy/fastify-response-caching)
442
451
  A Fastify plugin for caching the response.
452
+ - [`fastify-response-time`](https://github.com/lolo32/fastify-response-time) Add
453
+ `X-Response-Time` header at each request for Fastify, in milliseconds.
443
454
  - [`fastify-resty`](https://github.com/FastifyResty/fastify-resty) Fastify-based
444
455
  web framework with REST API routes auto-generation for TypeORM entities using
445
456
  DI and decorators.
@@ -478,6 +489,8 @@ section.
478
489
  Events with `reply.sse( … )` to Fastify.
479
490
  - [`fastify-sse-v2`](https://github.com/nodefactoryio/fastify-sse-v2) to provide
480
491
  Server-Sent Events using Async Iterators (supports newer versions of Fastify).
492
+ - [`fastify-ssr-vite`](https://github.com/nineohnine/fastify-ssr-vite) A simple
493
+ plugin for setting up server side rendering with vite.
481
494
  - [`fastify-stripe`](https://github.com/coopflow/fastify-stripe) Plugin to
482
495
  initialize and encapsulate [Stripe
483
496
  Node.js](https://github.com/stripe/stripe-node) instances in Fastify.
@@ -508,8 +521,6 @@ section.
508
521
  should use.
509
522
  - [`fastify-wamp-router`](https://github.com/lependu/fastify-wamp-router) Web
510
523
  Application Messaging Protocol router for Fastify.
511
- - [`fast-water`](https://github.com/tswayne/fast-water) A Fastify plugin for
512
- waterline. Decorates Fastify with waterline models.
513
524
  - [`fastify-webpack-hmr`](https://github.com/lependu/fastify-webpack-hmr)
514
525
  Webpack hot module reloading plugin for Fastify.
515
526
  - [`fastify-webpack-hot`](https://github.com/gajus/fastify-webpack-hot) Webpack
@@ -542,7 +553,11 @@ section.
542
553
  Fastify.
543
554
  - [`sequelize-fastify`](https://github.com/hsynlms/sequelize-fastify) A simple
544
555
  and lightweight Sequelize plugin for Fastify.
556
+ - [`typeorm-fastify-plugin`](https://github.com/jclemens24/fastify-typeorm) A simple
557
+ and updated Typeorm plugin for use with Fastify.
545
558
 
546
559
  #### [Community Tools](#community-tools)
547
560
  - [`fast-maker`](https://github.com/imjuni/fast-maker) route configuration
548
561
  generator by directory structure.
562
+ - [`simple-tjscli`](https://github.com/imjuni/simple-tjscli) CLI tool to
563
+ generate JSON Schema from TypeScript interfaces.
@@ -8,7 +8,39 @@ work after upgrading.
8
8
 
9
9
  ## Breaking Changes
10
10
 
11
- ### Deprecation of `app.use()`
11
+ ### Error handling composition ([#3261](https://github.com/fastify/fastify/pull/3261))
12
+
13
+ When an error is thrown in a async error handler function,
14
+ the upper-level error handler is executed if set.
15
+ If there is not a upper-level error handler, the default will
16
+ be executed as it was previously.
17
+
18
+ ```
19
+ import Fastify from 'fastify'
20
+
21
+ const fastify = Fastify()
22
+
23
+ fastify.register(async fastify => {
24
+ fastify.setErrorHandler(async err => {
25
+ console.log(err.message) // 'kaboom'
26
+ throw new Error('caught')
27
+ })
28
+
29
+ fastify.get('/encapsulated', async () => {
30
+ throw new Error('kaboom')
31
+ })
32
+ })
33
+
34
+ fastify.setErrorHandler(async err => {
35
+ console.log(err.message) // 'caught'
36
+ throw new Error('wrapped')
37
+ })
38
+
39
+ const res = await fastify.inject('/encapsulated')
40
+ console.log(res.json().message) // 'wrapped'
41
+ ```
42
+
43
+ ### Deprecation of `app.use()` ([#3506](https://github.com/fastify/fastify/pull/3506))
12
44
 
13
45
  Starting this version of Fastify, we have deprecated the use of `app.use()`. We
14
46
  have decided not to support the use of middlewares. Both
@@ -33,6 +65,35 @@ Starting from v4, all the `GET` routes will create a sibling `HEAD` route.
33
65
  You can revert this behaviour by setting the server's option `exposeHeadRoutes`
34
66
  to `false`.
35
67
 
68
+ ### Synchronous route definitions
69
+
70
+ The route registration has been made synchronous from v4.
71
+ This change was done to provide better error reporting for route definition.
72
+ As a result if you specify an `onRoute` hook in a plugin you should either:
73
+ * wrap your routes in a plugin (recommended)
74
+ * use `await register(...)`
75
+
76
+ For example refactor this:
77
+ ```
78
+ fastify.register((instance, opts, done) => {
79
+ instance.addHook('onRoute', (routeOptions) => {
80
+ const { path, method } = routeOptions;
81
+ console.log({ path, method });
82
+ });
83
+ done();
84
+ });
85
+ ```
86
+ Into this:
87
+ ```
88
+ await fastify.register((instance, opts, done) => {
89
+ instance.addHook('onRoute', (routeOptions) => {
90
+ const { path, method } = routeOptions;
91
+ console.log({ path, method });
92
+ });
93
+ done();
94
+ });
95
+ ```
96
+
36
97
  ## Non Breaking Changes
37
98
 
38
99
  ### Change of schema for multiple types
@@ -70,3 +131,10 @@ properties: {
70
131
  }
71
132
  }
72
133
  ```
134
+
135
+ ### Add `reply.trailers` methods ([#3794](https://github.com/fastify/fastify/pull/3794))
136
+
137
+ Fastify now supports the [HTTP Trailer] response headers.
138
+
139
+
140
+ [HTTP Trailer]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer
@@ -196,6 +196,11 @@ fastify.get('/html', (request, reply) => {
196
196
  reply.html({ hello: 'world' })
197
197
  })
198
198
  ```
199
+ Reminder that the `this` keyword is not available on *arrow functions*,
200
+ so when passing functions in *`decorateReply`* and *`decorateRequest`* as
201
+ a utility that also needs access to the `request` and `reply` instance,
202
+ a function that is defined using the `function` keyword is needed instead
203
+ of an *arrow function expression*.
199
204
 
200
205
  In the same way you can do this for the `request` object:
201
206
  ```js
@@ -24,23 +24,31 @@ snippet of code.
24
24
 
25
25
  ### Contents
26
26
 
27
- - [AWS Lambda](#aws-lambda)
27
+ - [AWS](#aws)
28
28
  - [Google Cloud Functions](#google-cloud-functions)
29
29
  - [Google Cloud Run](#google-cloud-run)
30
30
  - [Netlify Lambda](#netlify-lambda)
31
31
  - [Vercel](#vercel)
32
32
 
33
- ## AWS Lambda
33
+ ## AWS
34
+
35
+ To integrate with AWS, you have two choices of library:
36
+
37
+ - Using [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify)
38
+ which only adds API Gateway support but has heavy optimizations for fastify.
39
+ - Using [@h4ad/serverless-adapter](https://github.com/H4ad/serverless-adapter)
40
+ which is a little slower as it creates an HTTP request for each AWS event but
41
+ has support for more AWS services such as: AWS SQS, AWS SNS and others.
42
+
43
+ So you can decide which option is best for you, but you can test both libraries.
44
+
45
+ ### Using @fastify/aws-lambda
34
46
 
35
47
  The sample provided allows you to easily build serverless web
36
48
  applications/services and RESTful APIs using Fastify on top of AWS Lambda and
37
49
  Amazon API Gateway.
38
50
 
39
- *Note: Using
40
- [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify) is just one
41
- possible way.*
42
-
43
- ### app.js
51
+ #### app.js
44
52
 
45
53
  ```js
46
54
  const fastify = require('fastify');
@@ -71,7 +79,7 @@ When you execute your Fastify application like always, i.e. `node app.js` *(the
71
79
  detection for this could be `require.main === module`)*, you can normally listen
72
80
  to your port, so you can still run your Fastify function locally.
73
81
 
74
- ### lambda.js
82
+ #### lambda.js
75
83
 
76
84
  ```js
77
85
  const awsLambdaFastify = require('@fastify/aws-lambda')
@@ -99,14 +107,13 @@ signature to be used as a lambda `handler` function. This way all the incoming
99
107
  events (API Gateway requests) are passed to the `proxy` function of
100
108
  [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify).
101
109
 
102
- ### Example
110
+ #### Example
103
111
 
104
112
  An example deployable with
105
113
  [claudia.js](https://claudiajs.com/tutorials/serverless-express.html) can be
106
114
  found
107
115
  [here](https://github.com/claudiajs/example-projects/tree/master/fastify-app-lambda).
108
116
 
109
-
110
117
  ### Considerations
111
118
 
112
119
  - API Gateway does not support streams yet, so you are not able to handle
@@ -114,6 +121,12 @@ found
114
121
  - API Gateway has a timeout of 29 seconds, so it is important to provide a reply
115
122
  during this time.
116
123
 
124
+ #### Beyond API Gateway
125
+
126
+ If you need to integrate with more AWS services, take a look at
127
+ [@h4ad/serverless-adapter](https://viniciusl.com.br/serverless-adapter/docs/main/frameworks/fastify)
128
+ on Fastify to find out how to integrate.
129
+
117
130
  ## Google Cloud Functions
118
131
 
119
132
  ### Creation of Fastify instance
@@ -2,9 +2,7 @@
2
2
 
3
3
  ## HTTP2
4
4
 
5
- _Fastify_ offers **experimental support** for HTTP2 starting from Node 8 LTS,
6
- which includes HTTP2 without a flag; HTTP2 is supported over either HTTPS or
7
- plaintext.
5
+ _Fastify_ supports HTTP2 over either HTTPS (h2) or plaintext (h2c).
8
6
 
9
7
  Currently, none of the HTTP2-specific APIs are available through _Fastify_, but
10
8
  Node's `req` and `res` can be accessed through our `Request` and `Reply`
@@ -28,6 +28,7 @@ are Request/Reply hooks and application hooks:
28
28
  - [onRegister](#onregister)
29
29
  - [Scope](#scope)
30
30
  - [Route level hooks](#route-level-hooks)
31
+ - [Using Hooks to Inject Custom Properties](#using-hooks-to-inject-custom-properties)
31
32
  - [Diagnostics Channel Hooks](#diagnostics-channel-hooks)
32
33
 
33
34
  **Notice:** the `done` callback is not available when using `async`/`await` or
@@ -649,6 +650,57 @@ fastify.route({
649
650
 
650
651
  **Note**: both options also accept an array of functions.
651
652
 
653
+ ## Using Hooks to Inject Custom Properties
654
+ <a id="using-hooks-to-inject-custom-properties"></a>
655
+
656
+ You can use a hook to inject custom properties into incoming requests.
657
+ This is useful for reusing processed data from hooks in controllers.
658
+
659
+ A very common use case is, for example, checking user authentication based
660
+ on their token and then storing their recovered data into
661
+ the [Request](./Request.md) instance. This way, your controllers can read it
662
+ easily with `request.authenticatedUser` or whatever you want to call it.
663
+ That's how it might look like:
664
+
665
+ ```js
666
+ fastify.addHook('preParsing', async (request) => {
667
+ request.authenticatedUser = {
668
+ id: 42,
669
+ name: 'Jane Doe',
670
+ role: 'admin'
671
+ }
672
+ })
673
+
674
+ fastify.get('/me/is-admin', async function (req, reply) {
675
+ return { isAdmin: req.authenticatedUser?.role === 'admin' || false }
676
+ })
677
+ ```
678
+
679
+ Note that `.authenticatedUser` could actually be any property name
680
+ choosen by yourself. Using your own custom property prevents you
681
+ from mutating existing properties, which
682
+ would be a dangerous and destructive operation. So be careful and
683
+ make sure your property is entirely new, also using this approach
684
+ only for very specific and small cases like this example.
685
+
686
+ Regarding TypeScript in this example, you'd need to update the
687
+ `FastifyRequest` core interface to include your new property typing
688
+ (for more about it, see [TypeScript](./TypeScript.md) page), like:
689
+
690
+ ```ts
691
+ interface AuthenticatedUser { /* ... */ }
692
+
693
+ declare module 'fastify' {
694
+ export interface FastifyRequest {
695
+ authenticatedUser?: AuthenticatedUser;
696
+ }
697
+ }
698
+ ```
699
+
700
+ Although this is a very pragmatic approach, if you're trying to do
701
+ something more complex that changes these core objects, then
702
+ consider creating a custom [Plugin](./Plugins.md) instead.
703
+
652
704
  ## Diagnostics Channel Hooks
653
705
 
654
706
  > **Note:** The `diagnostics_channel` is currently experimental on Node.js, so
@@ -13,7 +13,7 @@ way we create a *directed acyclic graph* (DAG) and we will not have issues
13
13
  caused by cross dependencies.
14
14
 
15
15
  You may have already seen in the [Getting
16
- Started]((../Guides/Getting-Started.md#your-first-plugin)) guide how easy it is
16
+ Started](../Guides/Getting-Started.md#your-first-plugin) guide how easy it is
17
17
  to use this API:
18
18
  ```
19
19
  fastify.register(plugin, [options])
@@ -20,6 +20,9 @@
20
20
  - [.callNotFound()](#callnotfound)
21
21
  - [.getResponseTime()](#getresponsetime)
22
22
  - [.type(contentType)](#typecontenttype)
23
+ - [.getSerializationFunction(schema | httpStatus)](#getserializationfunction)
24
+ - [.compileSerializationSchema(schema, httpStatus)](#compileserializationschema)
25
+ - [.serializeInput(data, [schema | httpStatus], [httpStatus])](#serializeinput)
23
26
  - [.serializer(func)](#serializerfunc)
24
27
  - [.raw](#raw)
25
28
  - [.sent](#sent)
@@ -60,6 +63,16 @@ object that exposes the following functions and properties:
60
63
  - `.serialize(payload)` - Serializes the specified payload using the default
61
64
  JSON serializer or using the custom serializer (if one is set) and returns the
62
65
  serialized payload.
66
+ - `.getSerializationFunction(schema | httpStatus)` - Returns the serialization
67
+ function for the specified schema or http status, if any of either are set.
68
+ - `.compileSerializationSchema(schema, httpStatus)` - Compiles the specified
69
+ schema and returns a serialization function using the default (or customized)
70
+ `SerializerCompiler`. The optional `httpStatus` is forwarded to the
71
+ `SerializerCompiler` if provided, default to `undefined`.
72
+ - `.serializeInput(data, schema, [,httpStatus])` - Serializes the specified data
73
+ using the specified schema and returns the serialized payload.
74
+ If the optional `httpStatus` is provided, the function will use the serializer
75
+ function given for that HTTP Status Code. Default to `undefined`.
63
76
  - `.serializer(function)` - Sets a custom serializer for the payload.
64
77
  - `.send(payload)` - Sends the payload to the user, could be a plain text, a
65
78
  buffer, JSON, stream, or an Error object.
@@ -326,6 +339,169 @@ reply.type('text/html')
326
339
  If the `Content-Type` has a JSON subtype, and the charset parameter is not set,
327
340
  `utf-8` will be used as the charset by default.
328
341
 
342
+ ### .getSerializationFunction(schema | httpStatus)
343
+ <a id="getserializationfunction"></a>
344
+
345
+ By calling this function using a provided `schema` or `httpStatus`,
346
+ it will return a `serialzation` function that can be used to
347
+ serialize diverse inputs. It returns `undefined` if no
348
+ serialization function was found using either of the provided inputs.
349
+
350
+ This heavily depends of the `schema#responses` attached to the route, or
351
+ the serialization functions compiled by using `compileSerializationSchema`.
352
+
353
+ ```js
354
+ const serialize = reply
355
+ .getSerializationFunction({
356
+ type: 'object',
357
+ properties: {
358
+ foo: {
359
+ type: 'string'
360
+ }
361
+ }
362
+ })
363
+ serialize({ foo: 'bar' }) // '{"foo":"bar"}'
364
+
365
+ // or
366
+
367
+ const serialize = reply
368
+ .getSerializationFunction(200)
369
+ serialize({ foo: 'bar' }) // '{"foo":"bar"}'
370
+ ```
371
+
372
+ See [.compileSerializationSchema(schema, [httpStatus])](#compileserializationschema)
373
+ for more information on how to compile serialization schemas.
374
+
375
+ ### .compileSerializationSchema(schema, httpStatus)
376
+ <a id="compileserializationschema"></a>
377
+
378
+ This function will compile a serialization schema and
379
+ return a function that can be used to serialize data.
380
+ The function returned (a.k.a. _serialization function_) returned is compiled
381
+ by using the provided `SerializerCompiler`. Also this is cached by using
382
+ a `WeakMap` for reducing compilation calls.
383
+
384
+ The optional paramater `httpStatus`, if provided, is forwarded directly
385
+ the `SerializerCompiler`, so it can be used to compile the serialization
386
+ function if a custom `SerializerCompiler` is used.
387
+
388
+ This heavily depends of the `schema#responses` attached to the route, or
389
+ the serialization functions compiled by using `compileSerializationSchema`.
390
+
391
+ ```js
392
+ const serialize = reply
393
+ .compileSerializationSchema({
394
+ type: 'object',
395
+ properties: {
396
+ foo: {
397
+ type: 'string'
398
+ }
399
+ }
400
+ })
401
+ serialize({ foo: 'bar' }) // '{"foo":"bar"}'
402
+
403
+ // or
404
+
405
+ const serialize = reply
406
+ .compileSerializationSchema({
407
+ type: 'object',
408
+ properties: {
409
+ foo: {
410
+ type: 'string'
411
+ }
412
+ }
413
+ }, 200)
414
+ serialize({ foo: 'bar' }) // '{"foo":"bar"}'
415
+ ```
416
+
417
+ Note that you should be careful when using this function, as it will cache
418
+ the compiled serialization functions based on the schema provided. If the
419
+ schemas provided is mutated or changed, the serialization functions will not
420
+ detect that the schema has been altered and for instance it will reuse the
421
+ previously compiled serialization function based on the reference of the schema
422
+ previously provided.
423
+
424
+ If there's a need to change the properties of a schema, always opt to create
425
+ a totally new object, otherwise the implementation won't benefit from the cache
426
+ mechanism.
427
+
428
+ :Using the following schema as example:
429
+ ```js
430
+ const schema1 = {
431
+ type: 'object',
432
+ properties: {
433
+ foo: {
434
+ type: 'string'
435
+ }
436
+ }
437
+ }
438
+ ```
439
+
440
+ *Not*
441
+ ```js
442
+ const serialize = reply.compileSerializationSchema(schema1)
443
+
444
+ // Later on...
445
+ schema1.properties.foo.type. = 'integer'
446
+ const newSerialize = reply.compileSerializationSchema(schema1)
447
+
448
+ console.log(newSerialize === serialize) // true
449
+ ```
450
+
451
+ *Instead*
452
+ ```js
453
+ const serialize = reply.compileSerializationSchema(schema1)
454
+
455
+ // Later on...
456
+ const newSchema = Object.assign({}, schema1)
457
+ newSchema.properties.foo.type = 'integer'
458
+
459
+ const newSerialize = reply.compileSerializationSchema(newSchema)
460
+
461
+ console.log(newSerialize === serialize) // false
462
+ ```
463
+
464
+ ### .serializeInput(data, [schema | httpStatus], [httpStatus])
465
+ <a id="serializeinput"></a>
466
+
467
+ This function will serialize the input data based on the provided schema,
468
+ or http status code. If both provided, the `httpStatus` will take presedence.
469
+
470
+ If there is not a serialization function for a given `schema`, a new serialization
471
+ function will be compiled forwarding the `httpStatus` if provided.
472
+
473
+ ```js
474
+ reply
475
+ .serializeInput({ foo: 'bar'}, {
476
+ type: 'object',
477
+ properties: {
478
+ foo: {
479
+ type: 'string'
480
+ }
481
+ }
482
+ }) // '{"foo":"bar"}'
483
+
484
+ // or
485
+
486
+ reply
487
+ .serializeInput({ foo: 'bar'}, {
488
+ type: 'object',
489
+ properties: {
490
+ foo: {
491
+ type: 'string'
492
+ }
493
+ }
494
+ }, 200) // '{"foo":"bar"}'
495
+
496
+ // or
497
+
498
+ reply
499
+ .serializeInput({ foo: 'bar'}, 200) // '{"foo":"bar"}'
500
+ ```
501
+
502
+ See [.compileSerializationSchema(schema, [httpStatus])](#compileserializationschema)
503
+ for more information on how to compile serialization schemas.
504
+
329
505
  ### .serializer(func)
330
506
  <a id="serializer"></a>
331
507