fastify 3.15.1 → 3.17.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 (51) hide show
  1. package/.taprc +1 -5
  2. package/docs/Ecosystem.md +2 -0
  3. package/docs/LTS.md +18 -2
  4. package/docs/Reply.md +16 -0
  5. package/docs/Request.md +2 -0
  6. package/docs/Server.md +56 -1
  7. package/docs/TypeScript.md +1 -1
  8. package/docs/Validation-and-Serialization.md +1 -1
  9. package/examples/asyncawait.js +1 -2
  10. package/examples/{hooks-benchmark-async-await.js → benchmark/hooks-benchmark-async-await.js} +1 -2
  11. package/examples/{hooks-benchmark.js → benchmark/hooks-benchmark.js} +1 -2
  12. package/examples/benchmark/simple.js +30 -0
  13. package/examples/hooks.js +1 -2
  14. package/examples/http2.js +2 -2
  15. package/examples/https.js +2 -2
  16. package/examples/parser.js +1 -2
  17. package/examples/route-prefix.js +1 -2
  18. package/examples/shared-schema.js +1 -2
  19. package/examples/simple.js +0 -1
  20. package/examples/simple.mjs +1 -1
  21. package/examples/typescript-server.ts +1 -2
  22. package/examples/use-plugin.js +1 -2
  23. package/fastify.d.ts +18 -4
  24. package/fastify.js +3 -4
  25. package/lib/decorate.js +6 -1
  26. package/lib/errors.js +4 -0
  27. package/lib/pluginOverride.js +5 -0
  28. package/lib/reply.js +13 -2
  29. package/lib/request.js +5 -0
  30. package/lib/route.js +1 -0
  31. package/lib/schema-compilers.js +5 -65
  32. package/lib/schema-controller.js +6 -7
  33. package/lib/server.js +2 -0
  34. package/package.json +12 -10
  35. package/test/decorator.test.js +65 -8
  36. package/test/emit-warning.test.js +24 -20
  37. package/test/hooks.test.js +62 -0
  38. package/test/internals/plugin.test.js +22 -0
  39. package/test/internals/reply.test.js +37 -1
  40. package/test/internals/request.test.js +41 -2
  41. package/test/logger.test.js +28 -0
  42. package/test/schema-serialization.test.js +90 -1
  43. package/test/schema-special-usage.test.js +156 -0
  44. package/test/stream.test.js +128 -0
  45. package/test/types/fastify.test-d.ts +9 -1
  46. package/test/types/logger.test-d.ts +3 -1
  47. package/test/types/reply.test-d.ts +3 -2
  48. package/test/types/route.test-d.ts +12 -7
  49. package/types/context.d.ts +5 -1
  50. package/types/logger.d.ts +6 -4
  51. package/types/route.d.ts +2 -1
package/.taprc CHANGED
@@ -1,9 +1,5 @@
1
1
  ts: false
2
2
  jsx: false
3
3
  flow: false
4
- check-coverage: false
4
+ check-coverage: true
5
5
  coverage: true
6
- statements: 99
7
- lines: 99
8
- branches: 98
9
- functions: 99
package/docs/Ecosystem.md CHANGED
@@ -130,6 +130,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
130
130
  - [`fastify-mongo-memory`](https://github.com/chapuletta/fastify-mongo-memory) Fastify MongoDB in Memory Plugin for testing support.
131
131
  - [`fastify-mongoose-api`](https://github.com/jeka-kiselyov/fastify-mongoose-api) Fastify plugin to create REST API methods based on Mongoose MongoDB models.
132
132
  - [`fastify-mongoose-driver`](https://github.com/alex-ppg/fastify-mongoose) Fastify Mongoose plugin that connects to a MongoDB via the Mongoose plugin with support for Models.
133
+ - [`fastify-msgpack`](https://github.com/kenriortega/fastify-msgpack) Fastify and MessagePack, together at last. Uses @msgpack/msgpack by default.
133
134
  - [`fastify-multer`](https://github.com/fox1t/fastify-multer) Multer is a plugin for handling multipart/form-data, which is primarily used for uploading files.
134
135
  - [`fastify-nats`](https://github.com/mahmed8003/fastify-nats) Plugin to share [NATS](https://nats.io) client across Fastify.
135
136
  - [`fastify-no-additional-properties`](https://github.com/greguz/fastify-no-additional-properties) Add `additionalProperties: false` by default to your JSON Schemas.
@@ -151,6 +152,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
151
152
  - [`fastify-postgraphile`](https://github.com/alemagio/fastify-postgraphile) Plugin to integrate [PostGraphile](https://www.graphile.org/postgraphile/) in a Fastify project.
152
153
  - [`fastify-prettier`](https://github.com/hsynlms/fastify-prettier) A Fastify plugin that uses [prettier](https://github.com/prettier/prettier) under the hood to beautify outgoing responses and/or other things in the Fastify server.
153
154
  - [`fastify-print-routes`](https://github.com/ShogunPanda/fastify-print-routes) A Fastify plugin that prints all available routes.
155
+ - [`fastify-protobufjs`](https://github.com/kenriortega/fastify-protobufjs) Fastify and protobufjs, together at last. Uses protobufjs by default.
154
156
  - [`fastify-qrcode`](https://github.com/chonla/fastify-qrcode) This plugin utilizes [qrcode](https://github.com/soldair/node-qrcode) to generate QR Code.
155
157
  - [`fastify-qs`](https://github.com/webdevium/fastify-qs) A plugin for Fastify that adds support for parsing URL query parameters with [qs](https://github.com/ljharb/qs).
156
158
  - [`fastify-raw-body`](https://github.com/Eomm/fastify-raw-body) Add the `request.rawBody` field.
package/docs/LTS.md CHANGED
@@ -25,6 +25,19 @@ out in this document:
25
25
 
26
26
  A "month" is defined as 30 consecutive days.
27
27
 
28
+ > ## Security Releases and Semver
29
+ >
30
+ > As a consequence of providing long-term support for major releases, there
31
+ > are occasions where we need to release breaking changes as a _minor_
32
+ > version release. Such changes will _always_ be noted in the
33
+ > [release notes](https://github.com/fastify/fastify/releases).
34
+ >
35
+ > To avoid automatically receiving breaking security updates it is possible to use
36
+ > the tilde (`~`) range qualifier. For example, to get patches for the 3.15
37
+ > release, and avoid automatically updating to the 3.16 release, specify
38
+ > the dependency as `"fastify": "~3.15.x"`. This will leave your application vulnerable,
39
+ > so please use with caution.
40
+
28
41
  [semver]: https://semver.org/
29
42
 
30
43
  <a name="lts-schedule"></a>
@@ -41,12 +54,15 @@ A "month" is defined as 30 consecutive days.
41
54
 
42
55
  ### CI tested operating systems
43
56
 
44
- Fastify uses GitHub Actions for CI testing, please refer to [GitHub's documentation regarding workflow runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources) for further details on what the latest virtual environment is in relation to the YAML workflow labels below:
57
+ Fastify uses GitHub Actions for CI testing, please refer to
58
+ [GitHub's documentation regarding workflow runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources)
59
+ for further details on what the latest virtual environment is in relation to
60
+ the YAML workflow labels below:
45
61
 
46
62
  | OS | YAML Workflow Label | Package Manager | Node.js |
47
63
  |---------|------------------------|---------------------------|--------------|
48
64
  | Linux | `ubuntu-latest` | npm | 10,12,14,16 |
49
- | Linux | `ubuntu-16.04` | yarn,pnpm | 10,12 |
65
+ | Linux | `ubuntu-18.04` | yarn,pnpm | 10,12 |
50
66
  | Windows | `windows-latest` | npm | 10,12,14,16 |
51
67
  | MacOS | `macos-latest` | npm | 10,12,14,16 |
52
68
 
package/docs/Reply.md CHANGED
@@ -5,6 +5,7 @@
5
5
  - [Introduction](#introduction)
6
6
  - [.code(statusCode)](#codestatuscode)
7
7
  - [.statusCode](#statusCode)
8
+ - [.server](#server)
8
9
  - [.header(key, value)](#headerkey-value)
9
10
  - [.headers(object)](#headersobject)
10
11
  - [.getHeader(key)](#getheaderkey)
@@ -38,6 +39,7 @@ and properties:
38
39
  - `.code(statusCode)` - Sets the status code.
39
40
  - `.status(statusCode)` - An alias for `.code(statusCode)`.
40
41
  - `.statusCode` - Read and set the HTTP status code.
42
+ - `.server` - A reference to the fastify instance object.
41
43
  - `.header(name, value)` - Sets a response header.
42
44
  - `.headers(object)` - Sets all the keys of the object as response headers.
43
45
  - `.getHeader(name)` - Retrieve value of already set header.
@@ -87,6 +89,20 @@ if (reply.statusCode >= 299) {
87
89
  }
88
90
  ```
89
91
 
92
+ <a name="server"></a>
93
+ ### .server
94
+ The Fastify server instance, scoped to the current [encapsulation context](Encapsulation.md).
95
+
96
+ ```js
97
+ fastify.decorate('util', function util () {
98
+ return 'foo'
99
+ })
100
+
101
+ fastify.get('/', async function (req, rep) {
102
+ return rep.server.util() // foo
103
+ })
104
+ ```
105
+
90
106
  <a name="header"></a>
91
107
  ### .header(key, value)
92
108
  Sets a response header. If the value is omitted or undefined, it is coerced
package/docs/Request.md CHANGED
@@ -9,6 +9,7 @@ Request is a core Fastify object containing the following fields:
9
9
  - `headers` - the headers
10
10
  - `raw` - the incoming HTTP request from Node core
11
11
  - `req` *(deprecated, use `.raw` instead)* - the incoming HTTP request from Node core
12
+ - `server` - The Fastify server instance, scoped to the current [encapsulation context](Encapsulation.md)
12
13
  - `id` - the request id
13
14
  - `log` - the logger instance of the incoming request
14
15
  - `ip` - the IP address of the incoming request
@@ -31,6 +32,7 @@ fastify.post('/:params', options, function (request, reply) {
31
32
  console.log(request.params)
32
33
  console.log(request.headers)
33
34
  console.log(request.raw)
35
+ console.log(request.server)
34
36
  console.log(request.id)
35
37
  console.log(request.ip)
36
38
  console.log(request.ips)
package/docs/Server.md CHANGED
@@ -404,6 +404,19 @@ const fastify = require('fastify')({
404
404
  })
405
405
  ```
406
406
 
407
+ <a name="serializer-opts"></a>
408
+ ### `serializerOpts`
409
+
410
+ Customize the options of the default [`fast-json-stringify`](https://github.com/fastify/fast-json-stringify#options) instance that serialize the response's payload:
411
+
412
+ ```js
413
+ const fastify = require('fastify')({
414
+ serializerOpts: {
415
+ rounding: 'ceil'
416
+ }
417
+ })
418
+ ```
419
+
407
420
  <a name="http2-session-timeout"></a>
408
421
  ### `http2SessionTimeout`
409
422
 
@@ -841,7 +854,10 @@ This property can be used to set a function to format errors that happen while t
841
854
 
842
855
  <a name="schema-controller"></a>
843
856
  #### schemaController
844
- This property can be used to fully manage where the schemas of your application will be stored.
857
+ This property can be used to fully manage:
858
+ - `bucket`: where the schemas of your application will be stored
859
+ - `compilersFactory`: what module must compile the JSON schemas
860
+
845
861
  It can be useful when your schemas are stored in another data structure that is unknown to Fastify.
846
862
  See [issue #2446](https://github.com/fastify/fastify/issues/2446) for an example of what
847
863
  this property helps to resolve.
@@ -875,6 +891,45 @@ const fastify = Fastify({
875
891
  return allTheSchemaStored
876
892
  }
877
893
  }
894
+ },
895
+
896
+ /**
897
+ * The compilers factory let you to fully control the validator and serializer
898
+ * in the Fastify's lifecycle, providing the encapsulation to your compilers.
899
+ */
900
+ compilersFactory: {
901
+ /**
902
+ * This factory is called whenever a new validator instance is needed.
903
+ * It may be called whenever `fastify.register()` is called only if new schemas has been added to the
904
+ * encapsulation context.
905
+ * It may receive as input the schemas of the parent context if some schemas has been added.
906
+ * @param {object} externalSchemas these schemas will be returned by the `bucket.getSchemas()`. Needed to resolve the external references $ref.
907
+ * @param {object} ajvServerOption the server `ajv` options to build your compilers accordingly
908
+ */
909
+ buildValidator: function factory (externalSchemas, ajvServerOption) {
910
+ // This factory function must return a schema validator compiler.
911
+ // See [#schema-validator](Validation-and-Serialization.md#schema-validator) for details.
912
+ const yourAjvInstance = new Ajv(ajvServerOption.customOptions)
913
+ return function validatorCompiler ({ schema, method, url, httpPart }) {
914
+ return yourAjvInstance.compile(schema)
915
+ }
916
+ },
917
+
918
+ /**
919
+ * This factory is called whenever a new serializer instance is needed.
920
+ * It may be called whenever `fastify.register()` is called only if new schemas has been added to the
921
+ * encapsulation context.
922
+ * It may receive as input the schemas of the parent context if some schemas has been added.
923
+ * @param {object} externalSchemas these schemas will be returned by the `bucket.getSchemas()`. Needed to resolve the external references $ref.
924
+ * @param {object} serializerOptsServerOption the server `serializerOpts` options to build your compilers accordingly
925
+ */
926
+ buildSerializer: function factory (externalSchemas, serializerOptsServerOption) {
927
+ // This factory function must return a schema serializer compiler.
928
+ // See [#schema-serializer](Validation-and-Serialization.md#schema-serializer) for details.
929
+ return function serializerCompiler ({ schema, method, url, httpStatus }) {
930
+ return data => JSON.stringify(data)
931
+ }
932
+ }
878
933
  }
879
934
  }
880
935
  });
@@ -4,7 +4,7 @@
4
4
 
5
5
  The Fastify framework is written in vanilla JavaScript, and as such type definitions are not as easy to maintain; however, since version 2 and beyond, maintainers and contributors have put in a great effort to improve the types.
6
6
 
7
- The type system was changed in Fastify version 3. The new type system introduces generic constraining and defaulting, plus a new way to define schema types such as a request body, querystring, and more! As the team works on improving framework and type definition synergy, sometimes parts of the API will not be typed or may be typed incorrectly. We encourage you to **contribute** to help us fill in the gaps. Just make sure to read our [`CONTRIBUTING.md`](../CONTRIBUTING.md) file before getting started to make sure things go smoothly!
7
+ The type system was changed in Fastify version 3. The new type system introduces generic constraining and defaulting, plus a new way to define schema types such as a request body, querystring, and more! As the team works on improving framework and type definition synergy, sometimes parts of the API will not be typed or may be typed incorrectly. We encourage you to **contribute** to help us fill in the gaps. Just make sure to read our [`CONTRIBUTING.md`](https://github.com/fastify/fastify/blob/HEAD/CONTRIBUTING.md) file before getting started to make sure things go smoothly!
8
8
 
9
9
  > The documentation in this section covers Fastify version 3.x typings
10
10
 
@@ -356,7 +356,7 @@ fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
356
356
  return ajv.compile(schema)
357
357
  })
358
358
  ```
359
- _**Note:** If you use a custom instance of any validator (even Ajv), you have to add schemas to the validator instead of Fastify, since Fastify's default validator is no longer used, and astify's `addSchema` method has no idea what validator you are using._
359
+ _**Note:** If you use a custom instance of any validator (even Ajv), you have to add schemas to the validator instead of Fastify, since Fastify's default validator is no longer used, and Fastify's `addSchema` method has no idea what validator you are using._
360
360
 
361
361
  <a name="using-other-validation-libraries"></a>
362
362
  ##### Using other validation libraries
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../fastify')({ logger: true })
4
4
 
5
5
  const schema = {
6
6
  schema: {
@@ -33,5 +33,4 @@ fastify
33
33
 
34
34
  fastify.listen(3000, err => {
35
35
  if (err) throw err
36
- console.log(`server listening on ${fastify.server.address().port}`)
37
36
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../../fastify')({ logger: false })
4
4
 
5
5
  const opts = {
6
6
  schema: {
@@ -41,5 +41,4 @@ fastify.listen(3000, function (err) {
41
41
  if (err) {
42
42
  throw err
43
43
  }
44
- console.log(`server listening on ${fastify.server.address().port}`)
45
44
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../../fastify')({ logger: false })
4
4
 
5
5
  const opts = {
6
6
  schema: {
@@ -49,5 +49,4 @@ fastify.listen(3000, function (err) {
49
49
  if (err) {
50
50
  throw err
51
51
  }
52
- console.log(`server listening on ${fastify.server.address().port}`)
53
52
  })
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ const fastify = require('../../fastify')({
4
+ logger: false
5
+ })
6
+
7
+ const schema = {
8
+ schema: {
9
+ response: {
10
+ 200: {
11
+ type: 'object',
12
+ properties: {
13
+ hello: {
14
+ type: 'string'
15
+ }
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+
22
+ fastify
23
+ .get('/', schema, function (req, reply) {
24
+ reply
25
+ .send({ hello: 'world' })
26
+ })
27
+
28
+ fastify.listen(3000, (err, address) => {
29
+ if (err) throw err
30
+ })
package/examples/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../fastify')({ logger: true })
4
4
 
5
5
  const opts = {
6
6
  schema: {
@@ -85,5 +85,4 @@ fastify.listen(3000, function (err) {
85
85
  if (err) {
86
86
  throw err
87
87
  }
88
- console.log(`server listening on ${fastify.server.address().port}`)
89
88
  })
package/examples/http2.js CHANGED
@@ -7,7 +7,8 @@ const fastify = require('../fastify')({
7
7
  https: {
8
8
  key: fs.readFileSync(path.join(__dirname, '../test/https/fastify.key')),
9
9
  cert: fs.readFileSync(path.join(__dirname, '../test/https/fastify.cert'))
10
- }
10
+ },
11
+ logger: true
11
12
  })
12
13
 
13
14
  const opts = {
@@ -33,5 +34,4 @@ fastify
33
34
 
34
35
  fastify.listen(3000, err => {
35
36
  if (err) throw err
36
- console.log(`server listening on ${fastify.server.address().port}`)
37
37
  })
package/examples/https.js CHANGED
@@ -6,7 +6,8 @@ const fastify = require('../fastify')({
6
6
  https: {
7
7
  key: fs.readFileSync(path.join(__dirname, '../test/https/fastify.key')),
8
8
  cert: fs.readFileSync(path.join(__dirname, '../test/https/fastify.cert'))
9
- }
9
+ },
10
+ logger: true
10
11
  })
11
12
 
12
13
  const opts = {
@@ -32,5 +33,4 @@ fastify
32
33
 
33
34
  fastify.listen(3000, err => {
34
35
  if (err) throw err
35
- console.log(`server listening on ${fastify.server.address().port}`)
36
36
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../fastify')({ logger: true })
4
4
  const jsonParser = require('fast-json-body')
5
5
  const qs = require('qs')
6
6
 
@@ -38,5 +38,4 @@ fastify
38
38
 
39
39
  fastify.listen(3000, err => {
40
40
  if (err) throw err
41
- console.log(`server listening on ${fastify.server.address().port}`)
42
41
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../fastify')({ logger: true })
4
4
 
5
5
  const opts = {
6
6
  schema: {
@@ -35,5 +35,4 @@ fastify.listen(8000, function (err) {
35
35
  if (err) {
36
36
  throw err
37
37
  }
38
- console.log(`server listening on ${fastify.server.address().port}`)
39
38
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const fastify = require('../fastify')()
3
+ const fastify = require('../fastify')({ logger: true })
4
4
 
5
5
  fastify.addSchema({
6
6
  $id: 'https://foo/common.json',
@@ -33,5 +33,4 @@ fastify
33
33
 
34
34
  fastify.listen(3000, err => {
35
35
  if (err) throw err
36
- console.log(`server listening on ${fastify.server.address().port}`)
37
36
  })
@@ -27,5 +27,4 @@ fastify
27
27
 
28
28
  fastify.listen(3000, (err, address) => {
29
29
  if (err) throw err
30
- fastify.log.info(`server listening on ${address}`)
31
30
  })
@@ -2,7 +2,7 @@
2
2
  import { fastify } from '../fastify.js'
3
3
 
4
4
  const app = fastify({
5
- logger: false
5
+ logger: true
6
6
  })
7
7
 
8
8
  const schema = {
@@ -20,7 +20,7 @@ const server: FastifyInstance<
20
20
  Server,
21
21
  IncomingMessage,
22
22
  ServerResponse
23
- > = fastify();
23
+ > = fastify({ logger: true });
24
24
 
25
25
  // Define interfaces for our request. We can create these automatically
26
26
  // off our JSON Schema files (See TypeScript.md) but for the purpose of this
@@ -75,5 +75,4 @@ server.listen(8080, (err, address) => {
75
75
  console.error(err);
76
76
  process.exit(0);
77
77
  }
78
- console.log(`Server listening at ${address}`);
79
78
  });
@@ -1,4 +1,4 @@
1
- const fastify = require('../fastify')()
1
+ const fastify = require('../fastify')({ logger: true })
2
2
 
3
3
  const opts = {
4
4
  schema: {
@@ -22,5 +22,4 @@ fastify.listen(3000, function (err) {
22
22
  if (err) {
23
23
  throw err
24
24
  }
25
- console.log(`server listening on ${fastify.server.address().port}`)
26
25
  })
package/fastify.d.ts CHANGED
@@ -9,11 +9,12 @@ import { RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyD
9
9
  import { FastifyLoggerInstance, FastifyLoggerOptions } from './types/logger'
10
10
  import { FastifyInstance } from './types/instance'
11
11
  import { FastifyServerFactory } from './types/serverFactory'
12
- import * as ajv from 'ajv'
12
+ import { Options as AjvOptions } from '@fastify/ajv-compiler'
13
13
  import { FastifyError } from 'fastify-error'
14
14
  import { FastifyReply } from './types/reply'
15
15
  import { FastifySchemaValidationError } from './types/schema'
16
16
  import { ConstructorAction, ProtoAction } from "./types/content-type-parser";
17
+ import { Socket } from 'net'
17
18
 
18
19
  /**
19
20
  * Fastify factory function for the standard fastify http, https, or http2 server instance.
@@ -74,6 +75,15 @@ export type FastifyHttpsOptions<
74
75
 
75
76
  type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server ? HTTPVersion.V1 : HTTPVersion.V2
76
77
 
78
+ export interface ConnectionError extends Error {
79
+ code: string,
80
+ bytesParsed: number,
81
+ rawPacket: {
82
+ type: string,
83
+ data: number[]
84
+ }
85
+ }
86
+
77
87
  /**
78
88
  * Options for a fastify server instance. Utilizes conditional logic on the generic server parameter to enforce certain https and http2
79
89
  */
@@ -116,7 +126,7 @@ export type FastifyServerOptions<
116
126
  },
117
127
  return503OnClosing?: boolean,
118
128
  ajv?: {
119
- customOptions?: ajv.Options,
129
+ customOptions?: AjvOptions,
120
130
  plugins?: Function[]
121
131
  },
122
132
  frameworkErrors?: <RequestGeneric extends RequestGenericInterface = RequestGenericInterface>(
@@ -125,7 +135,11 @@ export type FastifyServerOptions<
125
135
  res: FastifyReply<RawServer, RawRequestDefaultExpression<RawServer>, RawReplyDefaultExpression<RawServer>>
126
136
  ) => void,
127
137
  rewriteUrl?: (req: RawRequestDefaultExpression<RawServer>) => string,
128
- schemaErrorFormatter?: (errors: FastifySchemaValidationError[], dataVar: string) => Error
138
+ schemaErrorFormatter?: (errors: FastifySchemaValidationError[], dataVar: string) => Error,
139
+ /**
140
+ * listener to error events emitted by client connections
141
+ */
142
+ clientErrorHandler?: (error: ConnectionError, socket: Socket) => void
129
143
  }
130
144
 
131
145
  type TrustProxyFunction = (address: string, hop: number) => boolean
@@ -150,7 +164,7 @@ export { FastifyReply } from './types/reply'
150
164
  export { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin } from './types/plugin'
151
165
  export { FastifyInstance } from './types/instance'
152
166
  export { FastifyLoggerOptions, FastifyLoggerInstance, FastifyLogFn, LogLevel } from './types/logger'
153
- export { FastifyContext } from './types/context'
167
+ export { FastifyContext, FastifyContextConfig } from './types/context'
154
168
  export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler } from './types/route'
155
169
  export * from './types/register'
156
170
  export { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction } from './types/content-type-parser'
package/fastify.js CHANGED
@@ -113,10 +113,6 @@ function fastify (options) {
113
113
  throw new Error(`ajv.plugins option should be an array, instead got '${typeof ajvOptions.plugins}'`)
114
114
  }
115
115
 
116
- ajvOptions.plugins = ajvOptions.plugins.map(plugin => {
117
- return Array.isArray(plugin) ? plugin : [plugin]
118
- })
119
-
120
116
  // Instance Fastify components
121
117
  const { logger, hasLogger } = createLogger(options)
122
118
 
@@ -290,6 +286,9 @@ function fastify (options) {
290
286
  initialConfig
291
287
  }
292
288
 
289
+ fastify[kReply].prototype.server = fastify
290
+ fastify[kRequest].prototype.server = fastify
291
+
293
292
  Object.defineProperties(fastify, {
294
293
  pluginName: {
295
294
  get () {
package/lib/decorate.js CHANGED
@@ -11,7 +11,8 @@ const {
11
11
  const {
12
12
  FST_ERR_DEC_ALREADY_PRESENT,
13
13
  FST_ERR_DEC_MISSING_DEPENDENCY,
14
- FST_ERR_DEC_AFTER_START
14
+ FST_ERR_DEC_AFTER_START,
15
+ FST_ERR_DEC_DEPENDENCY_INVALID_TYPE
15
16
  } = require('./errors')
16
17
 
17
18
  const warning = require('./warnings')
@@ -22,6 +23,10 @@ function decorate (instance, name, fn, dependencies) {
22
23
  }
23
24
 
24
25
  if (dependencies) {
26
+ if (!Array.isArray(dependencies)) {
27
+ throw new FST_ERR_DEC_DEPENDENCY_INVALID_TYPE(name)
28
+ }
29
+
25
30
  checkDependencies(instance, dependencies)
26
31
  }
27
32
 
package/lib/errors.js CHANGED
@@ -72,6 +72,10 @@ const codes = {
72
72
  'FST_ERR_DEC_ALREADY_PRESENT',
73
73
  "The decorator '%s' has already been added!"
74
74
  ),
75
+ FST_ERR_DEC_DEPENDENCY_INVALID_TYPE: createError(
76
+ 'FST_ERR_DEC_DEPENDENCY_INVALID_TYPE',
77
+ "The dependencies of decorator '%s' must be of type Array."
78
+ ),
75
79
  FST_ERR_DEC_MISSING_DEPENDENCY: createError(
76
80
  'FST_ERR_DEC_MISSING_DEPENDENCY',
77
81
  "The decorator is missing dependency '%s'."
@@ -37,8 +37,13 @@ module.exports = function override (old, fn, opts) {
37
37
  old[kChildren].push(instance)
38
38
  instance.ready = old[kAvvioBoot].bind(instance)
39
39
  instance[kChildren] = []
40
+
40
41
  instance[kReply] = Reply.buildReply(instance[kReply])
42
+ instance[kReply].prototype.server = instance
43
+
41
44
  instance[kRequest] = Request.buildRequest(instance[kRequest])
45
+ instance[kRequest].prototype.server = instance
46
+
42
47
  instance[kContentTypeParser] = ContentTypeParser.helpers.buildContentTypeParser(instance[kContentTypeParser])
43
48
  instance[kHooks] = buildHooks(instance[kHooks])
44
49
  instance[kRoutePrefix] = buildRoutePrefix(instance[kRoutePrefix], opts.prefix)
package/lib/reply.js CHANGED
@@ -101,6 +101,10 @@ Object.defineProperties(Reply.prototype, {
101
101
  set (value) {
102
102
  this.code(value)
103
103
  }
104
+ },
105
+ server: {
106
+ value: null,
107
+ writable: true
104
108
  }
105
109
  })
106
110
 
@@ -324,12 +328,14 @@ Reply.prototype.then = function (fulfilled, rejected) {
324
328
  return
325
329
  }
326
330
 
327
- eos(this.raw, function (err) {
331
+ eos(this.raw, (err) => {
328
332
  // We must not treat ERR_STREAM_PREMATURE_CLOSE as
329
333
  // an error because it is created by eos, not by the stream.
330
334
  if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {
331
335
  if (rejected) {
332
336
  rejected(err)
337
+ } else {
338
+ this.log && this.log.warn('unhandled rejection on reply.then')
333
339
  }
334
340
  } else {
335
341
  fulfilled()
@@ -426,6 +432,8 @@ function onSendEnd (reply, payload) {
426
432
 
427
433
  if (!reply[kReplyHeaders]['content-length']) {
428
434
  reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload)
435
+ } else if (req.raw.method !== 'HEAD' && reply[kReplyHeaders]['content-length'] !== Buffer.byteLength(payload)) {
436
+ reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload)
429
437
  }
430
438
 
431
439
  reply[kReplySent] = true
@@ -478,6 +486,8 @@ function sendStream (payload, res, reply) {
478
486
  payload.close(noop)
479
487
  } else if (typeof payload.abort === 'function') {
480
488
  payload.abort()
489
+ } else {
490
+ reply.log.warn('stream payload does not end properly')
481
491
  }
482
492
  }
483
493
  })
@@ -560,11 +570,12 @@ function handleError (reply, error, cb) {
560
570
  statusCode: { value: statusCode }
561
571
  }))
562
572
  } catch (err) {
573
+ // error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization
563
574
  reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed')
564
575
  res.statusCode = 500
565
576
  payload = serializeError({
566
577
  error: statusCodes['500'],
567
- message: err.message || '',
578
+ message: err.message,
568
579
  statusCode: 500
569
580
  })
570
581
  }
package/lib/request.js CHANGED
@@ -133,6 +133,7 @@ Object.defineProperties(Request.prototype, {
133
133
  },
134
134
  connection: {
135
135
  get () {
136
+ /* istanbul ignore next */
136
137
  if (semver.gte(process.versions.node, '13.0.0')) {
137
138
  warning.emit('FSTDEP005')
138
139
  }
@@ -163,6 +164,10 @@ Object.defineProperties(Request.prototype, {
163
164
  get () {
164
165
  return this.raw.headers
165
166
  }
167
+ },
168
+ server: {
169
+ value: null,
170
+ writable: true
166
171
  }
167
172
  })
168
173
 
package/lib/route.js CHANGED
@@ -326,6 +326,7 @@ function buildRouting (options) {
326
326
  // HTTP request entry point, the routing has already been executed
327
327
  function routeHandler (req, res, params, context) {
328
328
  if (closing === true) {
329
+ /* istanbul ignore next mac, windows */
329
330
  if (req.httpVersionMajor !== 2) {
330
331
  res.once('finish', () => req.destroy())
331
332
  res.setHeader('Connection', 'close')