fastify 3.5.0 → 3.8.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 (84) hide show
  1. package/docs/ContentTypeParser.md +3 -0
  2. package/docs/Ecosystem.md +7 -2
  3. package/docs/Hooks.md +0 -5
  4. package/docs/Lifecycle.md +2 -2
  5. package/docs/Logging.md +1 -1
  6. package/docs/Recommendations.md +17 -0
  7. package/docs/Reply.md +2 -2
  8. package/docs/Request.md +4 -2
  9. package/docs/Routes.md +21 -3
  10. package/docs/Server.md +51 -3
  11. package/docs/Style-Guide.md +180 -0
  12. package/docs/TypeScript.md +359 -359
  13. package/docs/Validation-and-Serialization.md +11 -5
  14. package/examples/parser.js +1 -1
  15. package/fastify.d.ts +2 -2
  16. package/fastify.js +39 -7
  17. package/lib/contentTypeParser.js +16 -11
  18. package/lib/context.js +5 -19
  19. package/lib/decorate.js +1 -1
  20. package/lib/errors.js +2 -2
  21. package/lib/fourOhFour.js +8 -7
  22. package/lib/handleRequest.js +5 -5
  23. package/lib/hooks.js +4 -4
  24. package/lib/logger.js +7 -7
  25. package/lib/pluginUtils.js +4 -2
  26. package/lib/reply.js +27 -24
  27. package/lib/reqIdGenFactory.js +2 -2
  28. package/lib/request.js +20 -8
  29. package/lib/route.js +12 -10
  30. package/lib/schemas.js +1 -1
  31. package/lib/server.js +5 -5
  32. package/lib/symbols.js +2 -1
  33. package/lib/validation.js +9 -8
  34. package/lib/warnings.js +3 -0
  35. package/lib/wrapThenable.js +2 -2
  36. package/package.json +10 -10
  37. package/test/404s.test.js +15 -15
  38. package/test/async-await.test.js +7 -7
  39. package/test/custom-parser-async.test.js +2 -2
  40. package/test/custom-parser.test.js +38 -8
  41. package/test/emit-warning.test.js +31 -0
  42. package/test/fastify-instance.test.js +33 -1
  43. package/test/helper.js +1 -1
  44. package/test/hooks.test.js +6 -6
  45. package/test/http2/head.test.js +1 -1
  46. package/test/http2/plain.test.js +1 -1
  47. package/test/http2/secure-with-fallback.test.js +1 -1
  48. package/test/http2/secure.test.js +1 -1
  49. package/test/http2/unknown-http-method.test.js +1 -1
  50. package/test/https/https.test.js +2 -1
  51. package/test/inject.test.js +2 -2
  52. package/test/internals/all.test.js +1 -1
  53. package/test/internals/hookRunner.test.js +1 -1
  54. package/test/internals/logger.test.js +1 -1
  55. package/test/internals/reply.test.js +62 -7
  56. package/test/internals/request.test.js +31 -5
  57. package/test/internals/version.test.js +43 -0
  58. package/test/listen.test.js +12 -0
  59. package/test/logger.test.js +11 -11
  60. package/test/nullable-validation.test.js +108 -0
  61. package/test/pretty-print.test.js +9 -14
  62. package/test/reply-error.test.js +2 -2
  63. package/test/request-error.test.js +81 -0
  64. package/test/route-hooks.test.js +10 -10
  65. package/test/stream.test.js +11 -11
  66. package/test/types/fastify.test-d.ts +1 -2
  67. package/test/types/instance.test-d.ts +17 -3
  68. package/test/types/logger.test-d.ts +35 -2
  69. package/test/types/register.test-d.ts +16 -0
  70. package/test/types/request.test-d.ts +1 -1
  71. package/test/types/route.test-d.ts +5 -0
  72. package/test/validation-error-handling.test.js +66 -0
  73. package/test/versioned-routes.test.js +55 -0
  74. package/types/.eslintrc.json +4 -1
  75. package/types/content-type-parser.d.ts +0 -15
  76. package/types/hooks.d.ts +138 -16
  77. package/types/instance.d.ts +86 -14
  78. package/types/logger.d.ts +13 -11
  79. package/types/plugin.d.ts +5 -7
  80. package/types/register.d.ts +8 -7
  81. package/types/request.d.ts +3 -1
  82. package/types/route.d.ts +38 -58
  83. package/types/schema.d.ts +4 -4
  84. package/types/serverFactory.d.ts +9 -9
@@ -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')({
@@ -16,7 +16,7 @@ fastify.addContentTypeParser('application/jsoff', function (request, payload, do
16
16
 
17
17
  // curl -X POST -d 'hello=world' -H'Content-type: application/x-www-form-urlencoded' http://localhost:3000/
18
18
  fastify.addContentTypeParser('application/x-www-form-urlencoded', function (request, payload, done) {
19
- var body = ''
19
+ let body = ''
20
20
  payload.on('data', function (data) {
21
21
  body += data
22
22
  })
package/fastify.d.ts CHANGED
@@ -119,8 +119,8 @@ export type FastifyServerOptions<
119
119
  type TrustProxyFunction = (address: string, hop: number) => boolean
120
120
 
121
121
  /* Export all additional types */
122
- export * from './types/request'
123
- export * from './types/reply'
122
+ export { FastifyRequest, RequestGenericInterface } from './types/request'
123
+ export { FastifyReply } from './types/reply'
124
124
  export { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin } from './types/plugin'
125
125
  export { FastifyInstance } from './types/instance'
126
126
  export { FastifyLoggerOptions, FastifyLoggerInstance, FastifyLogFn, LogLevel } from './types/logger'
package/fastify.js CHANGED
@@ -5,6 +5,7 @@ const http = require('http')
5
5
  const querystring = require('querystring')
6
6
  let lightMyRequest
7
7
  let version
8
+ let versionLoaded = false
8
9
 
9
10
  const {
10
11
  kAvvioBoot,
@@ -25,7 +26,8 @@ const {
25
26
  kState,
26
27
  kOptions,
27
28
  kPluginNameChain,
28
- kSchemaErrorFormatter
29
+ kSchemaErrorFormatter,
30
+ kErrorHandler
29
31
  } = require('./lib/symbols.js')
30
32
 
31
33
  const { createServer } = require('./lib/server')
@@ -57,6 +59,21 @@ const onBadUrlContext = {
57
59
  onError: []
58
60
  }
59
61
 
62
+ function defaultErrorHandler (error, request, reply) {
63
+ if (reply.statusCode < 500) {
64
+ reply.log.info(
65
+ { res: reply, err: error },
66
+ error && error.message
67
+ )
68
+ } else {
69
+ reply.log.error(
70
+ { req: request, res: reply, err: error },
71
+ error && error.message
72
+ )
73
+ }
74
+ reply.send(error)
75
+ }
76
+
60
77
  function fastify (options) {
61
78
  // Options validations
62
79
  options = options || {}
@@ -160,6 +177,7 @@ function fastify (options) {
160
177
  [kSchemas]: schemas,
161
178
  [kValidatorCompiler]: null,
162
179
  [kSchemaErrorFormatter]: options.schemaErrorFormatter,
180
+ [kErrorHandler]: defaultErrorHandler,
163
181
  [kSerializerCompiler]: null,
164
182
  [kReplySerializerDefault]: null,
165
183
  [kContentTypeParser]: new ContentTypeParser(
@@ -219,6 +237,8 @@ function fastify (options) {
219
237
  // custom parsers
220
238
  addContentTypeParser: ContentTypeParser.helpers.addContentTypeParser,
221
239
  hasContentTypeParser: ContentTypeParser.helpers.hasContentTypeParser,
240
+ getDefaultJsonParser: ContentTypeParser.defaultParsers.getDefaultJsonParser,
241
+ defaultTextParser: ContentTypeParser.defaultParsers.defaultTextParser,
222
242
  // Fastify architecture methods (initialized by Avvio)
223
243
  register: null,
224
244
  after: null,
@@ -266,11 +286,16 @@ function fastify (options) {
266
286
  },
267
287
  version: {
268
288
  get () {
269
- if (version === undefined) {
289
+ if (versionLoaded === false) {
270
290
  version = loadVersion()
271
291
  }
272
292
  return version
273
293
  }
294
+ },
295
+ errorHandler: {
296
+ get () {
297
+ return this[kErrorHandler]
298
+ }
274
299
  }
275
300
  })
276
301
 
@@ -504,8 +529,8 @@ function fastify (options) {
504
529
 
505
530
  function onBadUrl (path, req, res) {
506
531
  if (frameworkErrors) {
507
- var id = genReqId(req)
508
- var childLogger = logger.child({ reqId: id })
532
+ const id = genReqId(req)
533
+ const childLogger = logger.child({ reqId: id })
509
534
 
510
535
  childLogger.info({ req }, 'incoming request')
511
536
 
@@ -558,7 +583,7 @@ function fastify (options) {
558
583
  function setErrorHandler (func) {
559
584
  throwIfAlreadyStarted('Cannot call "setErrorHandler" when fastify instance is already started!')
560
585
 
561
- this._errorHandler = func
586
+ this[kErrorHandler] = func.bind(this)
562
587
  return this
563
588
  }
564
589
  }
@@ -591,10 +616,17 @@ function wrapRouting (httpHandler, { rewriteUrl, logger }) {
591
616
  }
592
617
 
593
618
  function loadVersion () {
619
+ versionLoaded = true
594
620
  const fs = require('fs')
595
621
  const path = require('path')
596
- const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json')))
597
- return pkg.version
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
+ }
598
630
  }
599
631
 
600
632
  /**
@@ -81,9 +81,10 @@ ContentTypeParser.prototype.existingParser = function (contentType) {
81
81
  }
82
82
 
83
83
  ContentTypeParser.prototype.getParser = function (contentType) {
84
+ /* eslint-disable no-var */
84
85
  for (var i = 0; i < this.parserList.length; i++) {
85
86
  if (contentType.indexOf(this.parserList[i]) > -1) {
86
- var parser = this.customParsers[this.parserList[i]]
87
+ const parser = this.customParsers[this.parserList[i]]
87
88
  this.cache.set(contentType, parser)
88
89
  return parser
89
90
  }
@@ -93,7 +94,7 @@ ContentTypeParser.prototype.getParser = function (contentType) {
93
94
  }
94
95
 
95
96
  ContentTypeParser.prototype.run = function (contentType, handler, request, reply) {
96
- var parser = this.cache.get(contentType) || this.getParser(contentType)
97
+ const parser = this.cache.get(contentType) || this.getParser(contentType)
97
98
 
98
99
  if (parser === undefined) {
99
100
  reply.send(new FST_ERR_CTP_INVALID_MEDIA_TYPE(contentType))
@@ -106,7 +107,7 @@ ContentTypeParser.prototype.run = function (contentType, handler, request, reply
106
107
  done
107
108
  )
108
109
  } else {
109
- var result
110
+ let result
110
111
 
111
112
  if (parser.isDeprecatedSignature) {
112
113
  result = parser.fn(request[kRequestPayloadStream], done)
@@ -130,9 +131,9 @@ ContentTypeParser.prototype.run = function (contentType, handler, request, reply
130
131
  }
131
132
 
132
133
  function rawBody (request, reply, options, parser, done) {
133
- var asString = parser.asString
134
- var limit = options.limit === null ? parser.bodyLimit : options.limit
135
- var contentLength = request.headers['content-length'] === undefined
134
+ const asString = parser.asString
135
+ const limit = options.limit === null ? parser.bodyLimit : options.limit
136
+ const contentLength = request.headers['content-length'] === undefined
136
137
  ? NaN
137
138
  : Number.parseInt(request.headers['content-length'], 10)
138
139
 
@@ -141,8 +142,8 @@ function rawBody (request, reply, options, parser, done) {
141
142
  return
142
143
  }
143
144
 
144
- var receivedLength = 0
145
- var body = asString === true ? '' : []
145
+ let receivedLength = 0
146
+ let body = asString === true ? '' : []
146
147
 
147
148
  const payload = request[kRequestPayloadStream] || request.raw
148
149
 
@@ -197,7 +198,7 @@ function rawBody (request, reply, options, parser, done) {
197
198
  body = Buffer.concat(body)
198
199
  }
199
200
 
200
- var result = parser.fn(request, body, done)
201
+ const result = parser.fn(request, body, done)
201
202
  if (result && typeof result.then === 'function') {
202
203
  result.then(body => done(null, body), done)
203
204
  }
@@ -211,9 +212,9 @@ function getDefaultJsonParser (onProtoPoisoning, onConstructorPoisoning) {
211
212
  if (body === '' || body == null) {
212
213
  return done(new FST_ERR_CTP_EMPTY_JSON_BODY(), undefined)
213
214
  }
214
-
215
+ let json
215
216
  try {
216
- var json = secureJson.parse(body, { protoAction: onProtoPoisoning, constructorAction: onConstructorPoisoning })
217
+ json = secureJson.parse(body, { protoAction: onProtoPoisoning, constructorAction: onConstructorPoisoning })
217
218
  } catch (err) {
218
219
  err.statusCode = 400
219
220
  return done(err, undefined)
@@ -279,4 +280,8 @@ module.exports.helpers = {
279
280
  addContentTypeParser,
280
281
  hasContentTypeParser
281
282
  }
283
+ module.exports.defaultParsers = {
284
+ getDefaultJsonParser,
285
+ defaultTextParser: defaultPlainTextParser
286
+ }
282
287
  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,26 +28,12 @@ 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
- var text = ''
48
- var separator = ', '
32
+ let text = ''
33
+ const separator = ', '
34
+ /* eslint-disable no-var */
49
35
  for (var i = 0; i < errors.length; i++) {
50
- var e = errors[i]
36
+ const e = errors[i]
51
37
  text += dataVar + (e.dataPath || '') + ' ' + e.message + separator
52
38
  }
53
39
  return new Error(text.slice(0, -separator.length))
package/lib/decorate.js CHANGED
@@ -56,7 +56,7 @@ function checkReplyExistence (name) {
56
56
  }
57
57
 
58
58
  function checkDependencies (instance, deps) {
59
- for (var i = 0; i < deps.length; i++) {
59
+ for (let i = 0; i < deps.length; i++) {
60
60
  if (!checkExistence(instance, deps[i])) {
61
61
  throw new FST_ERR_DEC_MISSING_DEPENDENCY(deps[i])
62
62
  }
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
 
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
  )
@@ -155,13 +156,13 @@ function fourOhFour (options) {
155
156
  // we might want to do some hard debugging
156
157
  // here, let's print out as much info as
157
158
  // we can
158
- var id = genReqId(req)
159
- var childLogger = logger.child({ reqId: id })
159
+ const id = genReqId(req)
160
+ const childLogger = logger.child({ reqId: id })
160
161
 
161
162
  childLogger.info({ req }, 'incoming request')
162
163
 
163
- var request = new Request(id, null, req, null, childLogger, fourOhFourContext)
164
- var reply = new Reply(res, request, childLogger)
164
+ const request = new Request(id, null, req, null, childLogger, fourOhFourContext)
165
+ const reply = new Reply(res, request, childLogger)
165
166
 
166
167
  request.log.warn('the default handler for 404 did not catch this, this is likely a fastify bug, please report it')
167
168
  request.log.warn(router.prettyPrint())
@@ -11,15 +11,15 @@ function handleRequest (err, request, reply) {
11
11
  return
12
12
  }
13
13
 
14
- var method = request.raw.method
15
- var headers = request.headers
14
+ const method = request.raw.method
15
+ const headers = request.headers
16
16
 
17
17
  if (method === 'GET' || method === 'HEAD') {
18
18
  handler(request, reply)
19
19
  return
20
20
  }
21
21
 
22
- var contentType = headers['content-type']
22
+ const contentType = headers['content-type']
23
23
 
24
24
  if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
25
25
  if (contentType === undefined) {
@@ -84,7 +84,7 @@ function preValidationCallback (err, request, reply) {
84
84
  return
85
85
  }
86
86
 
87
- var result = validateSchema(reply.context, request)
87
+ const result = validateSchema(reply.context, request)
88
88
  if (result) {
89
89
  if (reply.context.attachValidation === false) {
90
90
  reply.code(400).send(result)
@@ -118,7 +118,7 @@ function preHandlerCallback (err, request, reply) {
118
118
  return
119
119
  }
120
120
 
121
- var result
121
+ let result
122
122
 
123
123
  try {
124
124
  result = reply.context.handler(request, reply)
package/lib/hooks.js CHANGED
@@ -77,8 +77,8 @@ function buildHooks (h) {
77
77
 
78
78
  function hookRunnerApplication (hookName, boot, server, cb) {
79
79
  const hooks = server[kHooks][hookName]
80
- var i = 0
81
- var c = 0
80
+ let i = 0
81
+ let c = 0
82
82
 
83
83
  next()
84
84
 
@@ -151,7 +151,7 @@ function hookRunnerApplication (hookName, boot, server, cb) {
151
151
  }
152
152
 
153
153
  function hookRunner (functions, runner, request, reply, cb) {
154
- var i = 0
154
+ let i = 0
155
155
 
156
156
  function next (err) {
157
157
  if (err || i === functions.length) {
@@ -182,7 +182,7 @@ function hookRunner (functions, runner, request, reply, cb) {
182
182
  }
183
183
 
184
184
  function onSendHookRunner (functions, request, reply, payload, cb) {
185
- var i = 0
185
+ let i = 0
186
186
 
187
187
  function next (err, newPayload) {
188
188
  if (err) {
package/lib/logger.js CHANGED
@@ -23,9 +23,9 @@ function createPinoLogger (opts, stream) {
23
23
  delete opts.file
24
24
  }
25
25
 
26
- var prevLogger = opts.logger
27
- var prevGenReqId = opts.genReqId
28
- var logger = null
26
+ const prevLogger = opts.logger
27
+ const prevGenReqId = opts.genReqId
28
+ let logger = null
29
29
 
30
30
  if (prevLogger) {
31
31
  opts.logger = undefined
@@ -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,
@@ -65,7 +65,7 @@ const serializers = {
65
65
  }
66
66
 
67
67
  function now () {
68
- var ts = process.hrtime()
68
+ const ts = process.hrtime()
69
69
  return (ts[0] * 1e3) + (ts[1] / 1e6)
70
70
  }
71
71
 
@@ -105,9 +105,9 @@ function isValidLogger (logger) {
105
105
  return false
106
106
  }
107
107
 
108
- var result = true
108
+ let result = true
109
109
  const methods = ['info', 'error', 'debug', 'fatal', 'warn', 'trace', 'child']
110
- for (var i = 0; i < methods.length; i += 1) {
110
+ for (let i = 0; i < methods.length; i += 1) {
111
111
  if (!logger[methods[i]] || typeof logger[methods[i]] !== 'function') {
112
112
  result = false
113
113
  break
@@ -20,7 +20,7 @@ function getPluginName (func) {
20
20
  const cache = require.cache
21
21
  const keys = Object.keys(cache)
22
22
 
23
- for (var i = 0; i < keys.length; i++) {
23
+ for (let i = 0; i < keys.length; i++) {
24
24
  if (cache[keys[i]].exports === func) {
25
25
  return keys[i]
26
26
  }
@@ -107,7 +107,9 @@ function registerPluginName (fn) {
107
107
 
108
108
  function registerPlugin (fn) {
109
109
  registerPluginName.call(this, fn)
110
- checkVersion.call(this, fn)
110
+ if (this.version !== undefined) {
111
+ checkVersion.call(this, fn)
112
+ }
111
113
  checkDecorators.call(this, fn)
112
114
  checkDependencies.call(this, fn)
113
115
  return shouldSkipOverride(fn)
package/lib/reply.js CHANGED
@@ -125,8 +125,8 @@ Reply.prototype.send = function (payload) {
125
125
  return this
126
126
  }
127
127
 
128
- var contentType = this.getHeader('content-type')
129
- var hasContentType = contentType !== undefined
128
+ const contentType = this.getHeader('content-type')
129
+ const hasContentType = contentType !== undefined
130
130
 
131
131
  if (payload !== null) {
132
132
  if (Buffer.isBuffer(payload) || typeof payload.pipe === 'function') {
@@ -184,8 +184,8 @@ Reply.prototype.send = function (payload) {
184
184
 
185
185
  Reply.prototype.getHeader = function (key) {
186
186
  key = key.toLowerCase()
187
- var res = this.raw
188
- var value = this[kReplyHeaders][key]
187
+ const res = this.raw
188
+ let value = this[kReplyHeaders][key]
189
189
  if (value === undefined && res.hasHeader(key)) {
190
190
  value = res.getHeader(key)
191
191
  }
@@ -211,7 +211,7 @@ Reply.prototype.removeHeader = function (key) {
211
211
  }
212
212
 
213
213
  Reply.prototype.header = function (key, value) {
214
- var _key = key.toLowerCase()
214
+ const _key = key.toLowerCase()
215
215
 
216
216
  // default the value to ''
217
217
  value = value === undefined ? '' : value
@@ -233,7 +233,8 @@ Reply.prototype.header = function (key, value) {
233
233
  }
234
234
 
235
235
  Reply.prototype.headers = function (headers) {
236
- var keys = Object.keys(headers)
236
+ const keys = Object.keys(headers)
237
+ /* eslint-disable no-var */
237
238
  for (var i = 0; i < keys.length; i++) {
238
239
  this.header(keys[i], headers[keys[i]])
239
240
  }
@@ -289,7 +290,7 @@ Reply.prototype.callNotFound = function () {
289
290
  }
290
291
 
291
292
  Reply.prototype.getResponseTime = function () {
292
- var responseTime = 0
293
+ let responseTime = 0
293
294
 
294
295
  if (this[kReplyStartTime] !== undefined) {
295
296
  responseTime = now() - this[kReplyStartTime]
@@ -303,9 +304,9 @@ Reply.prototype.getResponseTime = function () {
303
304
  // - https://github.com/fastify/fastify/issues/1864 for the discussions
304
305
  // - https://promisesaplus.com/ for the definition of thenable
305
306
  // - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then for the signature
306
- Reply.prototype.then = function (fullfilled, rejected) {
307
+ Reply.prototype.then = function (fulfilled, rejected) {
307
308
  if (this.sent) {
308
- fullfilled()
309
+ fulfilled()
309
310
  return
310
311
  }
311
312
 
@@ -317,7 +318,7 @@ Reply.prototype.then = function (fullfilled, rejected) {
317
318
  rejected(err)
318
319
  }
319
320
  } else {
320
- fullfilled()
321
+ fulfilled()
321
322
  }
322
323
  })
323
324
  }
@@ -377,8 +378,9 @@ function wrapOnSendEnd (err, request, reply, payload) {
377
378
  }
378
379
 
379
380
  function onSendEnd (reply, payload) {
380
- var res = reply.raw
381
- var statusCode = res.statusCode
381
+ const res = reply.raw
382
+ const req = reply.request
383
+ const statusCode = res.statusCode
382
384
 
383
385
  if (payload === undefined || payload === null) {
384
386
  reply[kReplySent] = true
@@ -386,7 +388,8 @@ function onSendEnd (reply, payload) {
386
388
  // according to https://tools.ietf.org/html/rfc7230#section-3.3.2
387
389
  // we cannot send a content-length for 304 and 204, and all status code
388
390
  // < 200.
389
- if (statusCode >= 200 && statusCode !== 204 && statusCode !== 304) {
391
+ // For HEAD we don't overwrite the `content-length`
392
+ if (statusCode >= 200 && statusCode !== 204 && statusCode !== 304 && req.method !== 'HEAD') {
390
393
  reply[kReplyHeaders]['content-length'] = '0'
391
394
  }
392
395
 
@@ -428,8 +431,8 @@ function logStreamError (logger, err, res) {
428
431
  }
429
432
 
430
433
  function sendStream (payload, res, reply) {
431
- var sourceOpen = true
432
- var errorLogged = false
434
+ let sourceOpen = true
435
+ let errorLogged = false
433
436
 
434
437
  eos(payload, { readable: true, writable: false }, function (err) {
435
438
  sourceOpen = false
@@ -472,7 +475,7 @@ function sendStream (payload, res, reply) {
472
475
  // writeHead, and we need to resort to setHeader, which will trigger
473
476
  // a writeHead when there is data to send.
474
477
  if (!res.headersSent) {
475
- for (var key in reply[kReplyHeaders]) {
478
+ for (const key in reply[kReplyHeaders]) {
476
479
  res.setHeader(key, reply[kReplyHeaders][key])
477
480
  }
478
481
  } else {
@@ -499,8 +502,8 @@ function onErrorHook (reply, error, cb) {
499
502
 
500
503
  function handleError (reply, error, cb) {
501
504
  reply[kReplyIsRunningOnErrorHook] = false
502
- var res = reply.raw
503
- var statusCode = res.statusCode
505
+ const res = reply.raw
506
+ let statusCode = res.statusCode
504
507
  statusCode = (statusCode >= 400) ? statusCode : 500
505
508
  // treat undefined and null as same
506
509
  if (error != null) {
@@ -516,20 +519,20 @@ function handleError (reply, error, cb) {
516
519
 
517
520
  res.statusCode = statusCode
518
521
 
519
- var errorHandler = reply.context.errorHandler
522
+ const errorHandler = reply.context.errorHandler
520
523
  if (errorHandler && reply[kReplyErrorHandlerCalled] === false) {
521
524
  reply[kReplySent] = false
522
525
  reply[kReplyIsError] = false
523
526
  reply[kReplyErrorHandlerCalled] = true
524
527
  reply[kReplyHeaders]['content-length'] = undefined
525
- var result = errorHandler(error, reply.request, reply)
528
+ const result = errorHandler(error, reply.request, reply)
526
529
  if (result && typeof result.then === 'function') {
527
530
  wrapThenable(result, reply)
528
531
  }
529
532
  return
530
533
  }
531
534
 
532
- var payload = serializeError({
535
+ const payload = serializeError({
533
536
  error: statusCodes[statusCode + ''],
534
537
  code: error.code,
535
538
  message: error.message || '',
@@ -552,11 +555,11 @@ function handleError (reply, error, cb) {
552
555
  function setupResponseListeners (reply) {
553
556
  reply[kReplyStartTime] = now()
554
557
 
555
- var onResFinished = err => {
558
+ const onResFinished = err => {
556
559
  reply.raw.removeListener('finish', onResFinished)
557
560
  reply.raw.removeListener('error', onResFinished)
558
561
 
559
- var ctx = reply.context
562
+ const ctx = reply.context
560
563
 
561
564
  if (ctx && ctx.onResponse !== null) {
562
565
  hookRunner(
@@ -584,7 +587,7 @@ function onResponseCallback (err, request, reply) {
584
587
  return
585
588
  }
586
589
 
587
- var responseTime = reply.getResponseTime()
590
+ const responseTime = reply.getResponseTime()
588
591
 
589
592
  if (err != null) {
590
593
  reply.log.error({
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = function () {
4
- var maxInt = 2147483647
5
- var nextReqId = 0
4
+ const maxInt = 2147483647
5
+ let nextReqId = 0
6
6
  return function genReqId (req) {
7
7
  return (nextReqId = (nextReqId + 1) & maxInt)
8
8
  }