fastify 4.14.0 → 4.14.1

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.
@@ -284,7 +284,7 @@ fastify.addHook('onRequestAbort', async (request, reply) => {
284
284
  })
285
285
  ```
286
286
  The `onRequestAbort` hook is executed when a client closes the connection before
287
- the entire request has been received. Therefore, you will not be able to send
287
+ the entire request has been processed. Therefore, you will not be able to send
288
288
  data to the client.
289
289
 
290
290
  **Notice:** client abort detection is not completely reliable. See: [`Detecting-When-Clients-Abort.md`](../Guides/Detecting-When-Clients-Abort.md)
@@ -738,7 +738,8 @@ Fastify provides default error handlers for the most common use cases. It is
738
738
  possible to override one or more of those handlers with custom code using this
739
739
  option.
740
740
 
741
- *Note: Only `FST_ERR_BAD_URL` is implemented at the moment.*
741
+ *Note: Only `FST_ERR_BAD_URL` and `FST_ERR_ASYNC_CONSTRAINT` are implemented at
742
+ the moment.*
742
743
 
743
744
  ```js
744
745
  const fastify = require('fastify')({
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '4.14.0'
3
+ const VERSION = '4.14.1'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('http')
package/lib/context.js CHANGED
@@ -11,8 +11,8 @@ const {
11
11
  kLogLevel,
12
12
  kContentTypeParser,
13
13
  kRouteByFastify,
14
- kRequestValidateWeakMap,
15
- kReplySerializeWeakMap,
14
+ kRequestCacheValidateFns,
15
+ kReplyCacheSerializeFns,
16
16
  kPublicRouteContext
17
17
  } = require('./symbols.js')
18
18
 
@@ -68,8 +68,8 @@ function Context ({
68
68
  defaultSchemaErrorFormatter
69
69
  this[kRouteByFastify] = isFastify
70
70
 
71
- this[kRequestValidateWeakMap] = null
72
- this[kReplySerializeWeakMap] = null
71
+ this[kRequestCacheValidateFns] = null
72
+ this[kReplyCacheSerializeFns] = null
73
73
  this.validatorCompiler = validatorCompiler || null
74
74
  this.serializerCompiler = serializerCompiler || null
75
75
 
package/lib/reply.js CHANGED
@@ -18,7 +18,7 @@ const {
18
18
  kReplyNextErrorHandler,
19
19
  kDisableRequestLogging,
20
20
  kSchemaResponse,
21
- kReplySerializeWeakMap,
21
+ kReplyCacheSerializeFns,
22
22
  kSchemaController,
23
23
  kOptions,
24
24
  kRouteContext
@@ -323,7 +323,7 @@ Reply.prototype.getSerializationFunction = function (schemaOrStatus, contentType
323
323
  serialize = this[kRouteContext][kSchemaResponse]?.[schemaOrStatus]
324
324
  }
325
325
  } else if (typeof schemaOrStatus === 'object') {
326
- serialize = this[kRouteContext][kReplySerializeWeakMap]?.get(schemaOrStatus)
326
+ serialize = this[kRouteContext][kReplyCacheSerializeFns]?.get(schemaOrStatus)
327
327
  }
328
328
 
329
329
  return serialize
@@ -334,8 +334,8 @@ Reply.prototype.compileSerializationSchema = function (schema, httpStatus = null
334
334
  const { method, url } = request
335
335
 
336
336
  // Check if serialize function already compiled
337
- if (this[kRouteContext][kReplySerializeWeakMap]?.has(schema)) {
338
- return this[kRouteContext][kReplySerializeWeakMap].get(schema)
337
+ if (this[kRouteContext][kReplyCacheSerializeFns]?.has(schema)) {
338
+ return this[kRouteContext][kReplyCacheSerializeFns].get(schema)
339
339
  }
340
340
 
341
341
  const serializerCompiler = this[kRouteContext].serializerCompiler ||
@@ -360,11 +360,11 @@ Reply.prototype.compileSerializationSchema = function (schema, httpStatus = null
360
360
  // if it is not used
361
361
  // TODO: Explore a central cache for all the schemas shared across
362
362
  // encapsulated contexts
363
- if (this[kRouteContext][kReplySerializeWeakMap] == null) {
364
- this[kRouteContext][kReplySerializeWeakMap] = new WeakMap()
363
+ if (this[kRouteContext][kReplyCacheSerializeFns] == null) {
364
+ this[kRouteContext][kReplyCacheSerializeFns] = new WeakMap()
365
365
  }
366
366
 
367
- this[kRouteContext][kReplySerializeWeakMap].set(schema, serializeFn)
367
+ this[kRouteContext][kReplyCacheSerializeFns].set(schema, serializeFn)
368
368
 
369
369
  return serializeFn
370
370
  }
@@ -393,8 +393,8 @@ Reply.prototype.serializeInput = function (input, schema, httpStatus, contentTyp
393
393
  }
394
394
  } else {
395
395
  // Check if serialize function already compiled
396
- if (this[kRouteContext][kReplySerializeWeakMap]?.has(schema)) {
397
- serialize = this[kRouteContext][kReplySerializeWeakMap].get(schema)
396
+ if (this[kRouteContext][kReplyCacheSerializeFns]?.has(schema)) {
397
+ serialize = this[kRouteContext][kReplyCacheSerializeFns].get(schema)
398
398
  } else {
399
399
  serialize = this.compileSerializationSchema(schema, httpStatus, contentType)
400
400
  }
package/lib/request.js CHANGED
@@ -11,7 +11,7 @@ const {
11
11
  kSchemaQuerystring,
12
12
  kSchemaController,
13
13
  kOptions,
14
- kRequestValidateWeakMap,
14
+ kRequestCacheValidateFns,
15
15
  kRouteContext,
16
16
  kPublicRouteContext
17
17
  } = require('./symbols')
@@ -254,7 +254,7 @@ Object.defineProperties(Request.prototype, {
254
254
  const symbol = HTTP_PART_SYMBOL_MAP[httpPartOrSchema]
255
255
  return this[kRouteContext][symbol]
256
256
  } else if (typeof httpPartOrSchema === 'object') {
257
- return this[kRouteContext][kRequestValidateWeakMap]?.get(httpPartOrSchema)
257
+ return this[kRouteContext][kRequestCacheValidateFns]?.get(httpPartOrSchema)
258
258
  }
259
259
  }
260
260
  },
@@ -262,8 +262,8 @@ Object.defineProperties(Request.prototype, {
262
262
  value: function (schema, httpPart = null) {
263
263
  const { method, url } = this
264
264
 
265
- if (this[kRouteContext][kRequestValidateWeakMap]?.has(schema)) {
266
- return this[kRouteContext][kRequestValidateWeakMap].get(schema)
265
+ if (this[kRouteContext][kRequestCacheValidateFns]?.has(schema)) {
266
+ return this[kRouteContext][kRequestCacheValidateFns].get(schema)
267
267
  }
268
268
 
269
269
  const validatorCompiler = this[kRouteContext].validatorCompiler ||
@@ -287,11 +287,11 @@ Object.defineProperties(Request.prototype, {
287
287
  // if it is not used
288
288
  // TODO: Explore a central cache for all the schemas shared across
289
289
  // encapsulated contexts
290
- if (this[kRouteContext][kRequestValidateWeakMap] == null) {
291
- this[kRouteContext][kRequestValidateWeakMap] = new WeakMap()
290
+ if (this[kRouteContext][kRequestCacheValidateFns] == null) {
291
+ this[kRouteContext][kRequestCacheValidateFns] = new WeakMap()
292
292
  }
293
293
 
294
- this[kRouteContext][kRequestValidateWeakMap].set(schema, validateFn)
294
+ this[kRouteContext][kRequestCacheValidateFns].set(schema, validateFn)
295
295
 
296
296
  return validateFn
297
297
  }
@@ -317,8 +317,8 @@ Object.defineProperties(Request.prototype, {
317
317
  }
318
318
 
319
319
  if (validate == null) {
320
- if (this[kRouteContext][kRequestValidateWeakMap]?.has(schema)) {
321
- validate = this[kRouteContext][kRequestValidateWeakMap].get(schema)
320
+ if (this[kRouteContext][kRequestCacheValidateFns]?.has(schema)) {
321
+ validate = this[kRouteContext][kRequestCacheValidateFns].get(schema)
322
322
  } else {
323
323
  // We proceed to compile if there's no validate function yet
324
324
  validate = this.compileValidationSchema(schema, httpPart)
package/lib/route.js CHANGED
@@ -513,6 +513,7 @@ function handleOnRequestAbortHooksErrors (reply, err) {
513
513
  if (err) {
514
514
  reply.log.error({ err }, 'onRequestAborted hook failed')
515
515
  }
516
+ reply[kReplyIsError] = true
516
517
  }
517
518
 
518
519
  function handleTimeout () {
package/lib/symbols.js CHANGED
@@ -27,10 +27,9 @@ const keys = {
27
27
  kSchemaVisited: Symbol('fastify.schemas.visited'),
28
28
  // Request
29
29
  kRequest: Symbol('fastify.Request'),
30
- kRequestValidateFns: Symbol('fastify.request.cache.validateFns'),
31
30
  kRequestPayloadStream: Symbol('fastify.RequestPayloadStream'),
32
31
  kRequestAcceptVersion: Symbol('fastify.RequestAcceptVersion'),
33
- kRequestValidateWeakMap: Symbol('fastify.request.cache.validators'),
32
+ kRequestCacheValidateFns: Symbol('fastify.request.cache.validateFns'),
34
33
  // 404
35
34
  kFourOhFour: Symbol('fastify.404'),
36
35
  kCanSetNotFoundHandler: Symbol('fastify.canSetNotFoundHandler'),
@@ -51,7 +50,7 @@ const keys = {
51
50
  kReplyErrorHandlerCalled: Symbol('fastify.reply.errorHandlerCalled'),
52
51
  kReplyIsRunningOnErrorHook: Symbol('fastify.reply.isRunningOnErrorHook'),
53
52
  kReplySerializerDefault: Symbol('fastify.replySerializerDefault'),
54
- kReplySerializeWeakMap: Symbol('fastify.reply.cache.serializeFns'),
53
+ kReplyCacheSerializeFns: Symbol('fastify.reply.cache.serializeFns'),
55
54
  // This symbol is only meant to be used for fastify tests and should not be used for any other purpose
56
55
  kTestInternals: Symbol('fastify.testInternals'),
57
56
  kErrorHandler: Symbol('fastify.errorHandler'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "4.14.0",
3
+ "version": "4.14.1",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -3413,11 +3413,29 @@ test('onRequestAbort should be triggered', t => {
3413
3413
  const fastify = Fastify()
3414
3414
  let order = 0
3415
3415
 
3416
- t.plan(3)
3416
+ t.plan(9)
3417
3417
  t.teardown(() => fastify.close())
3418
3418
 
3419
3419
  fastify.addHook('onRequestAbort', function (req, done) {
3420
3420
  t.equal(++order, 1, 'called in hook')
3421
+ t.ok(req.pendingResolve, 'request has pendingResolve')
3422
+ req.pendingResolve()
3423
+ done()
3424
+ })
3425
+
3426
+ fastify.addHook('onError', function hook (request, reply, error, done) {
3427
+ t.same(error, { hello: 'world' }, 'onError should be called')
3428
+ t.ok(request.raw.aborted, 'request should be aborted')
3429
+ done()
3430
+ })
3431
+
3432
+ fastify.addHook('onSend', function hook (request, reply, payload, done) {
3433
+ t.equal(payload, '{"hello":"world"}', 'onSend should be called')
3434
+ done(null, payload)
3435
+ })
3436
+
3437
+ fastify.addHook('onResponse', function hook (request, reply, done) {
3438
+ t.fail('onResponse should not be called')
3421
3439
  done()
3422
3440
  })
3423
3441
 
@@ -3425,7 +3443,12 @@ test('onRequestAbort should be triggered', t => {
3425
3443
  method: 'GET',
3426
3444
  path: '/',
3427
3445
  async handler (request, reply) {
3428
- await sleep(1000)
3446
+ t.pass('handler called')
3447
+ let resolvePromise
3448
+ const promise = new Promise(resolve => { resolvePromise = resolve })
3449
+ request.pendingResolve = resolvePromise
3450
+ await promise
3451
+ t.pass('handler promise resolved')
3429
3452
  return { hello: 'world' }
3430
3453
  },
3431
3454
  async onRequestAbort (req) {
@@ -0,0 +1,33 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+
5
+ const { kRouteContext } = require('../../lib/symbols')
6
+ const Context = require('../../lib/context')
7
+
8
+ const Fastify = require('../..')
9
+
10
+ test('context', context => {
11
+ context.plan(1)
12
+
13
+ context.test('Should not contain undefined as key prop', async t => {
14
+ const app = Fastify()
15
+
16
+ app.get('/', (req, reply) => {
17
+ t.type(req[kRouteContext], Context)
18
+ t.type(reply[kRouteContext], Context)
19
+ t.notOk('undefined' in reply[kRouteContext])
20
+ t.notOk('undefined' in req[kRouteContext])
21
+
22
+ reply.send('hello world!')
23
+ })
24
+
25
+ try {
26
+ await app.inject('/')
27
+ } catch (e) {
28
+ t.fail(e)
29
+ }
30
+
31
+ t.plan(4)
32
+ })
33
+ })
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const { kReplySerializeWeakMap, kRouteContext } = require('../../lib/symbols')
4
+ const { kReplyCacheSerializeFns, kRouteContext } = require('../../lib/symbols')
5
5
  const Fastify = require('../../fastify')
6
6
 
7
7
  function getDefaultSchema () {
@@ -207,9 +207,9 @@ test('Reply#compileSerializationSchema', t => {
207
207
  fastify.get('/', (req, reply) => {
208
208
  const input = { hello: 'world' }
209
209
 
210
- t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
210
+ t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
211
211
  t.equal(reply.compileSerializationSchema(getDefaultSchema())(input), JSON.stringify(input))
212
- t.type(reply[kRouteContext][kReplySerializeWeakMap], WeakMap)
212
+ t.type(reply[kRouteContext][kReplyCacheSerializeFns], WeakMap)
213
213
  t.equal(reply.compileSerializationSchema(getDefaultSchema())(input), JSON.stringify(input))
214
214
 
215
215
  reply.send({ hello: 'world' })
@@ -408,9 +408,9 @@ test('Reply#getSerializationFunction', t => {
408
408
 
409
409
  fastify.get('/', (req, reply) => {
410
410
  t.notOk(reply.getSerializationFunction(getDefaultSchema()))
411
- t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
411
+ t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
412
412
  t.notOk(reply.getSerializationFunction('200'))
413
- t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
413
+ t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
414
414
 
415
415
  reply.send({ hello: 'world' })
416
416
  })
@@ -684,9 +684,9 @@ test('Reply#serializeInput', t => {
684
684
 
685
685
  fastify.get('/', (req, reply) => {
686
686
  const input = { hello: 'world' }
687
- t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
687
+ t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
688
688
  t.equal(reply.serializeInput(input, getDefaultSchema()), JSON.stringify(input))
689
- t.type(reply[kRouteContext][kReplySerializeWeakMap], WeakMap)
689
+ t.type(reply[kRouteContext][kReplyCacheSerializeFns], WeakMap)
690
690
 
691
691
  reply.send({ hello: 'world' })
692
692
  })
@@ -32,7 +32,7 @@ const doGet = function (url) {
32
32
  }
33
33
 
34
34
  test('Once called, Reply should return an object with methods', t => {
35
- t.plan(13)
35
+ t.plan(14)
36
36
  const response = { res: 'res' }
37
37
  const context = {}
38
38
  const request = { [kRouteContext]: context }
@@ -50,6 +50,8 @@ test('Once called, Reply should return an object with methods', t => {
50
50
  t.same(reply.raw, response)
51
51
  t.equal(reply[kRouteContext], context)
52
52
  t.equal(reply.request, request)
53
+ // Aim to not bad property keys (including Symbols)
54
+ t.notOk('undefined' in reply)
53
55
  })
54
56
 
55
57
  test('reply.send will logStream error and destroy the stream', t => {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { test } = require('tap')
4
4
  const Ajv = require('ajv')
5
- const { kRequestValidateWeakMap, kRouteContext } = require('../../lib/symbols')
5
+ const { kRequestCacheValidateFns, kRouteContext } = require('../../lib/symbols')
6
6
  const Fastify = require('../../fastify')
7
7
 
8
8
  const defaultSchema = {
@@ -231,11 +231,11 @@ test('#compileValidationSchema', subtest => {
231
231
  t.plan(5)
232
232
 
233
233
  fastify.get('/', (req, reply) => {
234
- t.equal(req[kRouteContext][kRequestValidateWeakMap], null)
234
+ t.equal(req[kRouteContext][kRequestCacheValidateFns], null)
235
235
  t.type(req.compileValidationSchema(defaultSchema), Function)
236
- t.type(req[kRouteContext][kRequestValidateWeakMap], WeakMap)
236
+ t.type(req[kRouteContext][kRequestCacheValidateFns], WeakMap)
237
237
  t.type(req.compileValidationSchema(Object.assign({}, defaultSchema)), Function)
238
- t.type(req[kRouteContext][kRequestValidateWeakMap], WeakMap)
238
+ t.type(req[kRouteContext][kRequestCacheValidateFns], WeakMap)
239
239
 
240
240
  reply.send({ hello: 'world' })
241
241
  })
@@ -424,7 +424,7 @@ test('#getValidationFunction', subtest => {
424
424
  req.getValidationFunction(defaultSchema)
425
425
  req.getValidationFunction('body')
426
426
 
427
- t.equal(req[kRouteContext][kRequestValidateWeakMap], null)
427
+ t.equal(req[kRouteContext][kRequestCacheValidateFns], null)
428
428
  reply.send({ hello: 'world' })
429
429
  })
430
430
 
@@ -724,9 +724,9 @@ test('#validate', subtest => {
724
724
  t.plan(3)
725
725
 
726
726
  fastify.get('/', (req, reply) => {
727
- t.equal(req[kRouteContext][kRequestValidateWeakMap], null)
727
+ t.equal(req[kRouteContext][kRequestCacheValidateFns], null)
728
728
  t.equal(req.validateInput({ hello: 'world' }, defaultSchema), true)
729
- t.type(req[kRouteContext][kRequestValidateWeakMap], WeakMap)
729
+ t.type(req[kRouteContext][kRequestCacheValidateFns], WeakMap)
730
730
 
731
731
  reply.send({ hello: 'world' })
732
732
  })
@@ -66,6 +66,8 @@ test('Regular request', t => {
66
66
  t.equal(request.routerMethod, context.config.method)
67
67
  t.equal(request.routeConfig, context[kPublicRouteContext].config)
68
68
  t.equal(request.routeSchema, context[kPublicRouteContext].schema)
69
+ // Aim to not bad property keys (including Symbols)
70
+ t.notOk('undefined' in request)
69
71
 
70
72
  // This will be removed, it's deprecated
71
73
  t.equal(request.connection, req.connection)