fastify 3.4.1 → 3.7.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 (54) hide show
  1. package/docs/ContentTypeParser.md +3 -0
  2. package/docs/Decorators.md +2 -0
  3. package/docs/Ecosystem.md +2 -1
  4. package/docs/Lifecycle.md +2 -2
  5. package/docs/Logging.md +1 -1
  6. package/docs/Reply.md +18 -0
  7. package/docs/Request.md +5 -1
  8. package/docs/Routes.md +2 -2
  9. package/docs/Server.md +55 -4
  10. package/docs/TypeScript.md +2 -1
  11. package/docs/Validation-and-Serialization.md +11 -5
  12. package/examples/simple.mjs +27 -0
  13. package/fastify.js +55 -7
  14. package/lib/contentTypeParser.js +4 -0
  15. package/lib/context.js +1 -16
  16. package/lib/errors.js +10 -2
  17. package/lib/fourOhFour.js +4 -3
  18. package/lib/logger.js +1 -1
  19. package/lib/pluginUtils.js +15 -0
  20. package/lib/reply.js +3 -3
  21. package/lib/request.js +26 -1
  22. package/lib/route.js +7 -3
  23. package/lib/symbols.js +2 -1
  24. package/lib/validation.js +1 -0
  25. package/lib/warnings.js +3 -0
  26. package/lib/wrapThenable.js +2 -2
  27. package/package.json +5 -5
  28. package/test/custom-parser.test.js +30 -0
  29. package/test/emit-warning.test.js +31 -0
  30. package/test/esm/index.test.js +15 -2
  31. package/test/esm/named-exports.mjs +13 -0
  32. package/test/fastify-instance.test.js +33 -1
  33. package/test/http2/secure.test.js +11 -0
  34. package/test/https/https.test.js +26 -0
  35. package/test/internals/request.test.js +8 -5
  36. package/test/internals/version.test.js +43 -0
  37. package/test/listen.test.js +16 -0
  38. package/test/logger.test.js +1 -1
  39. package/test/plugin.test.js +108 -0
  40. package/test/request-error.test.js +81 -0
  41. package/test/route.test.js +27 -0
  42. package/test/trust-proxy.test.js +42 -5
  43. package/test/types/decorate-request-reply.test-d.ts +18 -0
  44. package/test/types/instance.test-d.ts +27 -9
  45. package/test/types/logger.test-d.ts +63 -1
  46. package/test/types/register.test-d.ts +16 -0
  47. package/test/types/request.test-d.ts +1 -1
  48. package/test/types/schema.test-d.ts +5 -0
  49. package/test/validation-error-handling.test.js +66 -0
  50. package/types/instance.d.ts +7 -13
  51. package/types/logger.d.ts +90 -10
  52. package/types/register.d.ts +1 -0
  53. package/types/request.d.ts +20 -11
  54. package/types/schema.d.ts +2 -2
@@ -28,6 +28,9 @@ fastify.addContentTypeParser('application/jsoff', async function (request, paylo
28
28
 
29
29
  return res
30
30
  })
31
+
32
+ // Can use default JSON/Text parser for different content Types
33
+ fastify.addContentTypeParser('text/json', { parseAs: 'string' }, fastify.getDefaultJsonParser('ignore', 'ignore'))
31
34
  ```
32
35
 
33
36
  You can also use the `hasContentTypeParser` API to find if a specific content type parser already exists.
@@ -55,6 +55,8 @@ fastify.get('/', (req, reply) => {
55
55
  })
56
56
  ```
57
57
 
58
+ Note that it is important to keep initial shape of decorated field as close as possible to the value intended to be set dynamically in the future. Initialize a decorator as a `''` if the intended value is a string, and as `null` if it will be an object or a function.
59
+
58
60
  See
59
61
  [JavaScript engine fundamentals: Shapes and Inline Caches](https://web.archive.org/web/20200201163000/https://mathiasbynens.be/notes/shapes-ics)
60
62
  for more information on this topic.
package/docs/Ecosystem.md CHANGED
@@ -17,6 +17,7 @@ Plugins maintained by the fastify team are listed under [Core](#core) while plug
17
17
  - [`fastify-compress`](https://github.com/fastify/fastify-compress) Fastify compression utils.
18
18
  - [`fastify-cookie`](https://github.com/fastify/fastify-cookie) Parse and set cookie headers.
19
19
  - [`fastify-cors`](https://github.com/fastify/fastify-cors) Enables the use of CORS in a Fastify application.
20
+ - [`fastify-csrf`](https://github.com/fastify/fastify-csrf) A plugin for adding [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) protection to Fastify.
20
21
  - [`fastify-elasticsearch`](https://github.com/fastify/fastify-elasticsearch) Plugin to share the same ES client.
21
22
  - [`fastify-env`](https://github.com/fastify/fastify-env) Load and check configuration.
22
23
  - [`fastify-etag`](https://github.com/fastify/fastify-etag) Automatically generate etags for HTTP responses.
@@ -65,7 +66,6 @@ Plugins maintained by the fastify team are listed under [Core](#core) while plug
65
66
  - [`fastify-cloudevents`](https://github.com/smartiniOnGitHub/fastify-cloudevents) Fastify plugin to generate and forward Fastify events in the Cloudevents format.
66
67
  - [`fastify-cockroachdb`](https://github.com/alex-ppg/fastify-cockroachdb) Fastify plugin to connect to a CockroachDB PostgreSQL instance via the Sequelize ORM.
67
68
  - [`fastify-couchdb`](https://github.com/nigelhanlon/fastify-couchdb) Fastify plugin to add CouchDB support via [nano](https://github.com/apache/nano).
68
- - [`fastify-csrf`](https://github.com/Tarang11/fastify-csrf) A csrf plugin for Fastify.
69
69
  - [`fastify-decorators`](https://github.com/L2jLiga/fastify-decorators) Fastify plugin that provides the set of TypeScript decorators.
70
70
  - [`fastify-dynamodb`](https://github.com/matrus2/fastify-dynamodb) AWS DynamoDB plugin for Fastify. It exposes [AWS.DynamoDB.DocumentClient()](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html) object.
71
71
  - [`fastify-dynareg`](https://github.com/greguz/fastify-dynareg) Dynamic plugin register for Fastify.
@@ -128,6 +128,7 @@ Plugins maintained by the fastify team are listed under [Core](#core) while plug
128
128
  - [`fastify-rbac`](https://gitlab.com/m03geek/fastify-rbac) Fastify role-based access control plugin.
129
129
  - [`fastify-register-routes`](https://github.com/israeleriston/fastify-register-routes) Plugin to automatically load routes from a specified path and optionally limit loaded file names by a regular expression.
130
130
  - [`fastify-response-time`](https://github.com/lolo32/fastify-response-time) Add `X-Response-Time` header at each request for Fastify, in milliseconds.
131
+ - [`fastify-response-caching`](https://github.com/codeaholicguy/fastify-response-caching) A Fastify plugin for caching the response.
131
132
  - [`fastify-reverse-routes`](https://github.com/dimonnwc3/fastify-reverse-routes) Fastify reverse routes plugin, allows to defined named routes and build path using name and parameters.
132
133
  - [`fastify-rob-config`](https://github.com/jeromemacias/fastify-rob-config) Fastify Rob-Config integration.
133
134
  - [`fastify-schema-constraint`](https://github.com/Eomm/fastify-schema-constraint) Choose the JSON schema to use based on request parameters.
package/docs/Lifecycle.md CHANGED
@@ -10,7 +10,7 @@ Incoming Request
10
10
 
11
11
  └─▶ Instance Logger
12
12
 
13
- 404 ◀─┴─▶ onRequest Hook
13
+ 4**/5** ◀─┴─▶ onRequest Hook
14
14
 
15
15
  4**/5** ◀─┴─▶ preParsing Hook
16
16
 
@@ -20,7 +20,7 @@ Incoming Request
20
20
 
21
21
  415 ◀─┴─▶ Validation
22
22
 
23
- 400 ◀─┴─▶ preHandler Hook
23
+ 4**/5** ◀─┴─▶ preHandler Hook
24
24
 
25
25
  4**/5** ◀─┴─▶ User Handler
26
26
 
package/docs/Logging.md CHANGED
@@ -159,7 +159,7 @@ const fastify = Fastify({
159
159
  headers: request.headers,
160
160
  hostname: request.hostname,
161
161
  remoteAddress: request.ip,
162
- remotePort: request.connection.remotePort
162
+ remotePort: request.socket.remotePort
163
163
  }
164
164
  }
165
165
  }
package/docs/Reply.md CHANGED
@@ -15,6 +15,7 @@
15
15
  - [.callNotFound()](#callnotfound)
16
16
  - [.getResponseTime()](#getresponsetime)
17
17
  - [.type(contentType)](#typecontenttype)
18
+ - [.raw](#raw)
18
19
  - [.serializer(func)](#serializerfunc)
19
20
  - [.sent](#sent)
20
21
  - [.send(data)](#senddata)
@@ -207,6 +208,23 @@ reply
207
208
 
208
209
  See [`.send()`](#send) for more information on sending different types of values.
209
210
 
211
+ <a name="raw"></a>
212
+ ### .raw
213
+ This is the [`http.ServerResponse`](https://nodejs.org/dist/latest/docs/api/http.html#http_class_http_serverresponse) from Node core. While you're using the fastify `Reply` object, the use of `Reply.raw` functions is at your own risk as you're skipping all the fastify
214
+ logic of handling the http response. eg:
215
+
216
+ ```js
217
+ app.get('/cookie-2', (req, reply) => {
218
+ reply.setCookie('session', 'value', { secure: false }) // this will not be used
219
+
220
+ // in this case we are using only the nodejs http server response object
221
+ reply.raw.writeHead(200, { 'Content-Type': 'text/plain' })
222
+ reply.raw.write('ok')
223
+ reply.raw.end()
224
+ })
225
+ ```
226
+ Another example of the misuse of `Reply.raw` is explained in [Reply.md#getheaders](Reply.md#getheaders).
227
+
210
228
  <a name="sent"></a>
211
229
  ### .sent
212
230
 
package/docs/Request.md CHANGED
@@ -14,12 +14,15 @@ Request is a core Fastify object containing the following fields:
14
14
  - `ip` - the IP address of the incoming request
15
15
  - `ips` - an array of the IP addresses in the `X-Forwarded-For` header of the incoming request (only when the [`trustProxy`](Server.md#factory-trust-proxy) option is enabled)
16
16
  - `hostname` - the hostname of the incoming request
17
+ - `protocol` - the protocol of the incoming request (`https` or `http`)
17
18
  - `method` - the method of the incoming request
18
19
  - `url` - the url of the incoming request
19
20
  - `routerMethod` - the method defined for the router that is handling the request
20
21
  - `routerPath` - the path pattern defined for the router that is handling the request
21
22
  - `is404` - true if request is being handled by 404 handler, false if it is not
22
- - `connection` - the underlying connection of the incoming request
23
+ - `connection` - Deprecated, use `socket` instead. The underlying connection of the incoming request.
24
+ - `socket` - the underlying connection of the incoming request
25
+
23
26
 
24
27
  ```js
25
28
  fastify.post('/:params', options, function (request, reply) {
@@ -32,6 +35,7 @@ fastify.post('/:params', options, function (request, reply) {
32
35
  console.log(request.ip)
33
36
  console.log(request.ips)
34
37
  console.log(request.hostname)
38
+ console.log(request.protocol)
35
39
  request.log.info('some info')
36
40
  })
37
41
  ```
package/docs/Routes.md CHANGED
@@ -51,7 +51,7 @@ They need to be in
51
51
  * `onSend(request, reply, payload, done)`: a [function](Hooks.md#route-hooks) called right before a response is sent, it could also be an array of functions.
52
52
  * `onResponse(request, reply, done)`: a [function](Hooks.md#onresponse) called when a response has been sent, so you will not be able to send more data to the client. It could also be an array of functions.
53
53
  * `handler(request, reply)`: the function that will handle this request. The [Fastify server](Server.md) will be bound to `this` when the handler is called. Note: using an arrow function will break the binding of `this`.
54
- * `errorHandler(error, request, reply)`: a custom error handler for the scope of the request. Overrides the default error global handler, and anything set by [`setErrorHandler`](Server.md#setErrorHandler), for requests to the route.
54
+ * `errorHandler(error, request, reply)`: a custom error handler for the scope of the request. Overrides the default error global handler, and anything set by [`setErrorHandler`](Server.md#setErrorHandler), for requests to the route. To access the default handler, you can access `instance.errorHandler`. Note that this will point to fastify's default `errorHandler` only if a plugin hasn't overridden it already.
55
55
  * `validatorCompiler({ schema, method, url, httpPart })`: function that builds schemas for request validations. See the [Validation and Serialization](Validation-and-Serialization.md#schema-validator) documentation.
56
56
  * `serializerCompiler({ { schema, method, url, httpStatus } })`: function that builds schemas for response serialization. See the [Validation and Serialization](Validation-and-Serialization.md#schema-serializer) documentation.
57
57
  * `schemaErrorFormatter(errors, dataVar)`: function that formats the errors from the validation compiler. See the [Validation and Serialization](Validation-and-Serialization.md#error-handling) documentation. Overrides the global schema error formatter handler, and anything set by `setSchemaErrorFormatter`, for requests to the route.
@@ -360,7 +360,7 @@ const fastify = Fastify({
360
360
  headers: req.headers,
361
361
  hostname: req.hostname,
362
362
  remoteAddress: req.ip,
363
- remotePort: req.connection.remotePort
363
+ remotePort: req.socket.remotePort
364
364
  }
365
365
  }
366
366
  }
package/docs/Server.md CHANGED
@@ -293,13 +293,14 @@ const fastify = Fastify({ trustProxy: true })
293
293
 
294
294
  For more examples refer to [proxy-addr](https://www.npmjs.com/package/proxy-addr) package.
295
295
 
296
- You may access the `ip`, `ips`, and `hostname` values on the [`request`](Request.md) object.
296
+ You may access the `ip`, `ips`, `hostname` and `protocol` values on the [`request`](Request.md) object.
297
297
 
298
298
  ```js
299
299
  fastify.get('/', (request, reply) => {
300
300
  console.log(request.ip)
301
301
  console.log(request.ips)
302
302
  console.log(request.hostname)
303
+ console.log(request.protocol)
303
304
  })
304
305
  ```
305
306
 
@@ -478,7 +479,7 @@ const fastify = require('fastify')({
478
479
  <a name="rewrite-url"></a>
479
480
  ### `rewriteUrl`
480
481
 
481
- Set a sync callback function that must return a string that allows rewriting urls.
482
+ Set a sync callback function that must return a string that allows rewriting urls.
482
483
 
483
484
  > Rewriting a url will modify the `url` property of the `req` object
484
485
 
@@ -742,6 +743,10 @@ Important: If you have to deal with nested plugins the name differs with the usa
742
743
  #### log
743
744
  The logger instance, check [here](Logging.md).
744
745
 
746
+ <a name="version"></a>
747
+ #### version
748
+ Fastify version of the instance. Used for plugin support. See [Plugins](Plugins.md#handle-the-scope) for information on how the version is used by plugins.
749
+
745
750
  <a name="inject"></a>
746
751
  #### inject
747
752
  Fake http injection (for testing purposes) [here](Testing.md#inject).
@@ -833,17 +838,19 @@ fastify.register(function (instance, options, done) {
833
838
  <a name="set-error-handler"></a>
834
839
  #### setErrorHandler
835
840
 
836
- `fastify.setErrorHandler(handler(error, request, reply))`: Set a function that will be called whenever an error happens. The handler is fully encapsulated, so different plugins can set different error handlers. *async-await* is supported as well.<br>
841
+ `fastify.setErrorHandler(handler(error, request, reply))`: Set a function that will be called whenever an error happens. The handler is bound to the Fastify instance, and is fully encapsulated, so different plugins can set different error handlers. *async-await* is supported as well.<br>
837
842
  *Note: If the error `statusCode` is less than 400, Fastify will automatically set it at 500 before calling the error handler.*
838
843
 
839
844
  ```js
840
845
  fastify.setErrorHandler(function (error, request, reply) {
841
846
  // Log error
847
+ this.log.error(error)
842
848
  // Send error response
849
+ reply.status(409).send({ ok: false })
843
850
  })
844
851
  ```
845
852
 
846
- Fastify is provided with a default function that is called if no error handler is set and that logs the error with respect to its `statusCode`:
853
+ Fastify is provided with a default function that is called if no error handler is set. It can be accessed using `fastify.errorHandler` and it logs the error with respect to its `statusCode`.
847
854
 
848
855
  ```js
849
856
  var statusCode = error.statusCode
@@ -876,6 +883,50 @@ fastify.ready(() => {
876
883
  })
877
884
  ```
878
885
 
886
+ <a name="addContentTypeParser"></a>
887
+ #### addContentTypeParser
888
+
889
+ `fastify.addContentTypeParser(content-type, options, parser)` is used to pass custom parser for a given content type. Useful for adding parsers for custom content types, e.g. `text/json, application/vnd.oasis.opendocument.text`. `content-type` can be a string or string array.
890
+
891
+ ```js
892
+ // The two arguments passed to getDefaultJsonParser are for ProtoType poisoning and Constructor Poisoning configuration respectively. The possible values are 'ignore', 'remove', 'error'. ignore skips all validations and it is similar to calling JSON.parse() directly. See the <a href="https://github.com/fastify/secure-json-parse#api">`secure-json-parse` documentation</a> for more information.
893
+
894
+ fastify.addContentTypeParser('text/json', { asString: true }, fastify.getDefaultJsonParser('ignore', 'ignore'))
895
+ ```
896
+
897
+ <a name="getDefaultJsonParser"></a>
898
+ #### getDefaultJsonParser
899
+
900
+ `fastify.getDefaultJsonParser(onProtoPoisoning, onConstructorPoisoning)` takes two arguments. First argument is ProtoType poisoning configuration and second argument is constructor poisoning configuration. See the <a href="https://github.com/fastify/secure-json-parse#api">`secure-json-parse` documentation</a> for more information.
901
+
902
+
903
+ <a name="defaultTextParser"></a>
904
+ #### defaultTextParser
905
+
906
+ `fastify.defaultTextParser()` can be used to parse content as plain text.
907
+
908
+ ```js
909
+ fastify.addContentTypeParser('text/json', { asString: true }, fastify.defaultTextParser())
910
+ ```
911
+
912
+ <a name="errorHandler"></a>
913
+ #### errorHandler
914
+
915
+ `fastify.errorHandler` can be used to handle errors using fastify's default error handler.
916
+
917
+ ```js
918
+ fastify.get('/', {
919
+ errorHandler: (error, request, reply) => {
920
+ if (error.code === 'SOMETHING_SPECIFIC') {
921
+ reply.send({ custom: 'response' })
922
+ return
923
+ }
924
+
925
+ fastify.errorHandler(error, request, response)
926
+ }
927
+ }, handler)
928
+ ```
929
+
879
930
  <a name="initial-config"></a>
880
931
  #### initialConfig
881
932
 
@@ -10,6 +10,7 @@ The type system was changed in Fastify version 3. The new type system introduces
10
10
 
11
11
  > Plugins may or may not include typings. See [Plugins](#plugins) for more information. We encourage users to send pull requests to improve typings support.
12
12
 
13
+ 🚨 Don't foget to install `@types/node`
13
14
 
14
15
  ## Learn By Example
15
16
 
@@ -243,7 +244,7 @@ One of Fastify's most distinguishable features is its extensive plugin ecosystem
243
244
  ```bash
244
245
  npm init -y
245
246
  npm i fastify fastify-plugin
246
- npm i -D typescript
247
+ npm i -D typescript @types/node
247
248
  ```
248
249
  2. Add a `build` script to the `"scripts"` section and `'index.d.ts'` to the `"types"` section of the `package.json` file:
249
250
  ```json
@@ -163,13 +163,19 @@ const bodyJsonSchema = {
163
163
  }
164
164
 
165
165
  const queryStringJsonSchema = {
166
- name: { type: 'string' },
167
- excitement: { type: 'integer' }
166
+ type: 'object',
167
+ properties: {
168
+ name: { type: 'string' },
169
+ excitement: { type: 'integer' }
170
+ }
168
171
  }
169
172
 
170
173
  const paramsJsonSchema = {
171
- par1: { type: 'string' },
172
- par2: { type: 'number' }
174
+ type: 'object',
175
+ properties: {
176
+ par1: { type: 'string' },
177
+ par2: { type: 'number' }
178
+ }
173
179
  }
174
180
 
175
181
  const headersJsonSchema = {
@@ -198,7 +204,7 @@ fastify.post('/the/url', { schema }, handler)
198
204
 
199
205
  You can provide a list of plugins you want to use with Ajv:
200
206
 
201
- > Refer to [`ajv options`](Server.md#factory-ajv) to check plugins format
207
+ > Refer to [`ajv options`](Server.md#ajv) to check plugins format
202
208
 
203
209
  ```js
204
210
  const fastify = require('fastify')({
@@ -0,0 +1,27 @@
1
+ // works on Node v14.13.0+
2
+ import { fastify } from '../fastify.js'
3
+
4
+ const app = fastify({
5
+ logger: false
6
+ })
7
+
8
+ const schema = {
9
+ schema: {
10
+ response: {
11
+ 200: {
12
+ type: 'object',
13
+ properties: {
14
+ hello: {
15
+ type: 'string'
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
22
+
23
+ app.get('/', schema, async function (req, reply) {
24
+ return { hello: 'world' }
25
+ })
26
+
27
+ app.listen(3000).catch(console.error)
package/fastify.js CHANGED
@@ -4,6 +4,8 @@ const Avvio = require('avvio')
4
4
  const http = require('http')
5
5
  const querystring = require('querystring')
6
6
  let lightMyRequest
7
+ let version
8
+ let versionLoaded = false
7
9
 
8
10
  const {
9
11
  kAvvioBoot,
@@ -24,7 +26,8 @@ const {
24
26
  kState,
25
27
  kOptions,
26
28
  kPluginNameChain,
27
- kSchemaErrorFormatter
29
+ kSchemaErrorFormatter,
30
+ kErrorHandler
28
31
  } = require('./lib/symbols.js')
29
32
 
30
33
  const { createServer } = require('./lib/server')
@@ -56,6 +59,21 @@ const onBadUrlContext = {
56
59
  onError: []
57
60
  }
58
61
 
62
+ function defaultErrorHandler (error, request, reply) {
63
+ if (reply.statusCode >= 500) {
64
+ reply.log.error(
65
+ { req: request, res: reply, err: error },
66
+ error && error.message
67
+ )
68
+ } else if (reply.statusCode >= 400) {
69
+ reply.log.info(
70
+ { res: reply, err: error },
71
+ error && error.message
72
+ )
73
+ }
74
+ reply.send(error)
75
+ }
76
+
59
77
  function fastify (options) {
60
78
  // Options validations
61
79
  options = options || {}
@@ -159,6 +177,7 @@ function fastify (options) {
159
177
  [kSchemas]: schemas,
160
178
  [kValidatorCompiler]: null,
161
179
  [kSchemaErrorFormatter]: options.schemaErrorFormatter,
180
+ [kErrorHandler]: defaultErrorHandler,
162
181
  [kSerializerCompiler]: null,
163
182
  [kReplySerializerDefault]: null,
164
183
  [kContentTypeParser]: new ContentTypeParser(
@@ -218,6 +237,8 @@ function fastify (options) {
218
237
  // custom parsers
219
238
  addContentTypeParser: ContentTypeParser.helpers.addContentTypeParser,
220
239
  hasContentTypeParser: ContentTypeParser.helpers.hasContentTypeParser,
240
+ getDefaultJsonParser: ContentTypeParser.defaultParsers.getDefaultJsonParser,
241
+ defaultTextParser: ContentTypeParser.defaultParsers.defaultTextParser,
221
242
  // Fastify architecture methods (initialized by Avvio)
222
243
  register: null,
223
244
  after: null,
@@ -255,13 +276,26 @@ function fastify (options) {
255
276
  }
256
277
  },
257
278
  prefix: {
258
- get: function () { return this[kRoutePrefix] }
279
+ get () { return this[kRoutePrefix] }
259
280
  },
260
281
  validatorCompiler: {
261
- get: function () { return this[kValidatorCompiler] }
282
+ get () { return this[kValidatorCompiler] }
262
283
  },
263
284
  serializerCompiler: {
264
- get: function () { return this[kSerializerCompiler] }
285
+ get () { return this[kSerializerCompiler] }
286
+ },
287
+ version: {
288
+ get () {
289
+ if (versionLoaded === false) {
290
+ version = loadVersion()
291
+ }
292
+ return version
293
+ }
294
+ },
295
+ errorHandler: {
296
+ get () {
297
+ return this[kErrorHandler]
298
+ }
265
299
  }
266
300
  })
267
301
 
@@ -549,7 +583,7 @@ function fastify (options) {
549
583
  function setErrorHandler (func) {
550
584
  throwIfAlreadyStarted('Cannot call "setErrorHandler" when fastify instance is already started!')
551
585
 
552
- this._errorHandler = func
586
+ this[kErrorHandler] = func.bind(this)
553
587
  return this
554
588
  }
555
589
  }
@@ -581,6 +615,20 @@ function wrapRouting (httpHandler, { rewriteUrl, logger }) {
581
615
  }
582
616
  }
583
617
 
618
+ function loadVersion () {
619
+ versionLoaded = true
620
+ const fs = require('fs')
621
+ const path = require('path')
622
+ try {
623
+ const pkgPath = path.join(__dirname, 'package.json')
624
+ fs.accessSync(pkgPath, fs.constants.R_OK)
625
+ const pkg = JSON.parse(fs.readFileSync(pkgPath))
626
+ return pkg.name === 'fastify' ? pkg.version : undefined
627
+ } catch (e) {
628
+ return undefined
629
+ }
630
+ }
631
+
584
632
  /**
585
633
  * These export configurations enable JS and TS developers
586
634
  * to consumer fastify in whatever way best suits their needs.
@@ -592,6 +640,6 @@ function wrapRouting (httpHandler, { rewriteUrl, logger }) {
592
640
  * - `import fastify from 'fastify'`
593
641
  * - `import fastify, { TSC_definition } from 'fastify'`
594
642
  */
595
- fastify.fastify = fastify
596
- fastify.default = fastify
597
643
  module.exports = fastify
644
+ module.exports.fastify = fastify
645
+ module.exports.default = fastify
@@ -279,4 +279,8 @@ module.exports.helpers = {
279
279
  addContentTypeParser,
280
280
  hasContentTypeParser
281
281
  }
282
+ module.exports.defaultParsers = {
283
+ getDefaultJsonParser,
284
+ defaultTextParser: defaultPlainTextParser
285
+ }
282
286
  module.exports[kTestInternals] = { rawBody }
package/lib/context.js CHANGED
@@ -17,7 +17,7 @@ function Context (schema, handler, Reply, Request, contentTypeParser, config, er
17
17
  this.preHandler = null
18
18
  this.onResponse = null
19
19
  this.config = config
20
- this.errorHandler = errorHandler || defaultErrorHandler
20
+ this.errorHandler = errorHandler
21
21
  this._middie = null
22
22
  this._parserOptions = { limit: bodyLimit || null }
23
23
  this.logLevel = logLevel
@@ -28,21 +28,6 @@ function Context (schema, handler, Reply, Request, contentTypeParser, config, er
28
28
  this.schemaErrorFormatter = schemaErrorFormatter || defaultSchemaErrorFormatter
29
29
  }
30
30
 
31
- function defaultErrorHandler (error, request, reply) {
32
- if (reply.statusCode >= 500) {
33
- reply.log.error(
34
- { req: request, res: reply, err: error },
35
- error && error.message
36
- )
37
- } else if (reply.statusCode >= 400) {
38
- reply.log.info(
39
- { res: reply, err: error },
40
- error && error.message
41
- )
42
- }
43
- reply.send(error)
44
- }
45
-
46
31
  function defaultSchemaErrorFormatter (errors, dataVar) {
47
32
  var text = ''
48
33
  var separator = ', '
package/lib/errors.js CHANGED
@@ -171,8 +171,8 @@ const codes = {
171
171
  /**
172
172
  * wrapThenable
173
173
  */
174
- FST_ERR_PROMISE_NOT_FULLFILLED: createError(
175
- 'FST_ERR_PROMISE_NOT_FULLFILLED',
174
+ FST_ERR_PROMISE_NOT_FULFILLED: createError(
175
+ 'FST_ERR_PROMISE_NOT_FULFILLED',
176
176
  "Promise may not be fulfilled with 'undefined' when statusCode is not 204"
177
177
  ),
178
178
 
@@ -211,6 +211,14 @@ const codes = {
211
211
  FST_ERR_REOPENED_SERVER: createError(
212
212
  'FST_ERR_REOPENED_SERVER',
213
213
  'Fastify is already listening'
214
+ ),
215
+
216
+ /**
217
+ * plugin
218
+ */
219
+ FST_ERR_PLUGIN_VERSION_MISMATCH: createError(
220
+ 'FST_ERR_PLUGIN_VERSION_MISMATCH',
221
+ "fastify-plugin: %s - expected '%s' fastify version, '%s' is installed"
214
222
  )
215
223
  }
216
224
 
package/lib/fourOhFour.js CHANGED
@@ -15,7 +15,8 @@ const {
15
15
  kBodyLimit,
16
16
  kLogLevel,
17
17
  kFourOhFourContext,
18
- kHooks
18
+ kHooks,
19
+ kErrorHandler
19
20
  } = require('./symbols.js')
20
21
  const { lifecycleHooks } = require('./hooks')
21
22
  const fourOhFourContext = {
@@ -28,7 +29,7 @@ const fourOhFourContext = {
28
29
  /**
29
30
  * Each fastify instance have a:
30
31
  * kFourOhFourLevelInstance: point to a fastify instance that has the 404 handler setted
31
- * kCanSetNotFoundHandler: bool to track if the 404 handler has alredy been set
32
+ * kCanSetNotFoundHandler: bool to track if the 404 handler has already been set
32
33
  * kFourOhFour: the singleton instance of this 404 module
33
34
  * kFourOhFourContext: the context in the reply object where the handler will be executed
34
35
  */
@@ -124,7 +125,7 @@ function fourOhFour (options) {
124
125
  this[kRequest],
125
126
  this[kContentTypeParser],
126
127
  opts.config || {},
127
- this._errorHandler,
128
+ this[kErrorHandler],
128
129
  this[kBodyLimit],
129
130
  this[kLogLevel]
130
131
  )
package/lib/logger.js CHANGED
@@ -53,7 +53,7 @@ const serializers = {
53
53
  version: req.headers['accept-version'],
54
54
  hostname: req.hostname,
55
55
  remoteAddress: req.ip,
56
- remotePort: req.connection.remotePort
56
+ remotePort: req.socket.remotePort
57
57
  }
58
58
  },
59
59
  err: pino.stdSerializers.err,
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const semver = require('semver')
3
4
  const assert = require('assert')
4
5
  const registeredPlugins = Symbol.for('registered-plugin')
5
6
  const {
@@ -7,6 +8,7 @@ const {
7
8
  kRequest,
8
9
  kTestInternals
9
10
  } = require('./symbols.js')
11
+ const { FST_ERR_PLUGIN_VERSION_MISMATCH } = require('./errors')
10
12
 
11
13
  function getMeta (fn) {
12
14
  return fn[Symbol.for('plugin-meta')]
@@ -84,6 +86,16 @@ function _checkDecorators (instance, decorators) {
84
86
  })
85
87
  }
86
88
 
89
+ function checkVersion (fn) {
90
+ const meta = getMeta(fn)
91
+ if (!meta) return
92
+
93
+ const requiredVersion = meta.fastify
94
+ if (!requiredVersion) return
95
+
96
+ if (!semver.satisfies(this.version, requiredVersion)) throw new FST_ERR_PLUGIN_VERSION_MISMATCH(meta.name, requiredVersion, this.version)
97
+ }
98
+
87
99
  function registerPluginName (fn) {
88
100
  const meta = getMeta(fn)
89
101
  if (!meta) return
@@ -95,6 +107,9 @@ function registerPluginName (fn) {
95
107
 
96
108
  function registerPlugin (fn) {
97
109
  registerPluginName.call(this, fn)
110
+ if (this.version !== undefined) {
111
+ checkVersion.call(this, fn)
112
+ }
98
113
  checkDecorators.call(this, fn)
99
114
  checkDependencies.call(this, fn)
100
115
  return shouldSkipOverride(fn)
package/lib/reply.js CHANGED
@@ -303,9 +303,9 @@ Reply.prototype.getResponseTime = function () {
303
303
  // - https://github.com/fastify/fastify/issues/1864 for the discussions
304
304
  // - https://promisesaplus.com/ for the definition of thenable
305
305
  // - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then for the signature
306
- Reply.prototype.then = function (fullfilled, rejected) {
306
+ Reply.prototype.then = function (fulfilled, rejected) {
307
307
  if (this.sent) {
308
- fullfilled()
308
+ fulfilled()
309
309
  return
310
310
  }
311
311
 
@@ -317,7 +317,7 @@ Reply.prototype.then = function (fullfilled, rejected) {
317
317
  rejected(err)
318
318
  }
319
319
  } else {
320
- fullfilled()
320
+ fulfilled()
321
321
  }
322
322
  })
323
323
  }