@nxtedition/lib 15.0.53 → 15.0.55

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 (2) hide show
  1. package/http.js +43 -39
  2. package/package.json +9 -9
package/http.js CHANGED
@@ -2,7 +2,6 @@ const createError = require('http-errors')
2
2
  const { performance } = require('perf_hooks')
3
3
  const requestTarget = require('request-target')
4
4
  const querystring = require('fast-querystring')
5
- const assert = require('assert')
6
5
  const compose = require('koa-compose')
7
6
  const http = require('http')
8
7
  const fp = require('lodash/fp')
@@ -24,6 +23,30 @@ function genReqId() {
24
23
  return `req-${nextReqId.toString(36)}`
25
24
  }
26
25
 
26
+ const kResolve = Symbol('resolve')
27
+
28
+ function onTimeout() {
29
+ this.destroy(new createError.RequestTimeout())
30
+ }
31
+
32
+ function onRequestError(err) {
33
+ this.log.error({ err }, 'request error')
34
+ }
35
+
36
+ function onRequestClose() {
37
+ this.log.debug('request closed')
38
+ }
39
+
40
+ function onResponseError(err) {
41
+ this.log.error({ err }, 'response error')
42
+ this[kResolve](Promise.reject(err))
43
+ }
44
+
45
+ function onResponseClose() {
46
+ this.log.debug('response closed')
47
+ this[kResolve](null)
48
+ }
49
+
27
50
  module.exports.request = async function request(ctx, next) {
28
51
  const { req, res, logger } = ctx
29
52
  const startTime = performance.now()
@@ -39,10 +62,10 @@ module.exports.request = async function request(ctx, next) {
39
62
  }
40
63
 
41
64
  ctx.id = req.id = req.headers['request-id'] || genReqId()
42
- ctx.logger = req.log = logger.child({ req })
65
+ ctx.logger = req.log = res.log = logger.child({ req })
43
66
  ctx.signal = signal
44
67
  ctx.method = req.method
45
- ctx.query = ctx.url.search ? querystring.parse(ctx.url.search.slice(1)) : {}
68
+ ctx.query = ctx.url.search.length > 1 ? querystring.parse(ctx.url.search.slice(1)) : {}
46
69
 
47
70
  if (req.method === 'GET' || req.method === 'HEAD') {
48
71
  req.resume() // Dump the body if there is one.
@@ -54,55 +77,34 @@ module.exports.request = async function request(ctx, next) {
54
77
 
55
78
  reqLogger = ctx.logger
56
79
  if (!isHealthcheck) {
57
- reqLogger.debug({ req }, 'request started')
80
+ reqLogger.debug('request started')
58
81
  } else {
59
- reqLogger.trace({ req }, 'request started')
82
+ reqLogger.trace('request started')
60
83
  }
61
84
 
62
85
  await Promise.all([
63
86
  next(),
64
- new Promise((resolve, reject) => {
65
- res
66
- .on('timeout', function () {
67
- this.destroy(new createError.RequestTimeout())
68
- })
69
- .on('error', function (err) {
70
- reqLogger.error({ err }, 'response error')
71
- reject(err)
72
- })
73
- .on('close', function () {
74
- reqLogger.debug('response closed')
75
- resolve(null)
76
- })
77
- req
78
- .on('timeout', function () {
79
- this.destroy(new createError.RequestTimeout())
80
- })
81
- .on('error', function (err) {
82
- reqLogger.error({ err }, 'request error')
83
- })
84
- .on('close', function () {
85
- reqLogger.debug('request closed')
86
- })
87
+ new Promise((resolve) => {
88
+ res[kResolve] = resolve
89
+
90
+ res.on('timeout', onTimeout).on('error', onResponseError).on('close', onResponseClose)
91
+
92
+ req.on('timeout', onTimeout).on('error', onRequestError).on('close', onRequestClose)
87
93
  }),
88
94
  ])
89
95
 
90
- assert(req.aborted || res.writableEnded)
91
-
92
96
  const responseTime = Math.round(performance.now() - startTime)
93
97
 
94
- reqLogger = reqLogger.child({ res, responseTime })
95
-
96
- if (req.aborted) {
97
- reqLogger.debug('request aborted')
98
+ if (!res.writableEnded) {
99
+ reqLogger.debug({ res, responseTime }, 'request aborted')
98
100
  } else if (res.statusCode >= 500) {
99
- reqLogger.error('request error')
101
+ reqLogger.error({ res, responseTime }, 'request error')
100
102
  } else if (res.statusCode >= 400) {
101
- reqLogger.warn('request failed')
103
+ reqLogger.warn({ res, responseTime }, 'request failed')
102
104
  } else if (!isHealthcheck) {
103
- reqLogger.debug('request completed')
105
+ reqLogger.debug({ res, responseTime }, 'request completed')
104
106
  } else {
105
- reqLogger.trace('request completed')
107
+ reqLogger.trace({ res, responseTime }, 'request completed')
106
108
  }
107
109
 
108
110
  ac.abort()
@@ -162,7 +164,7 @@ module.exports.request = async function request(ctx, next) {
162
164
  } else {
163
165
  reqLogger = reqLogger.child({ res, err, reason, responseTime })
164
166
 
165
- if (req.aborted || err.name === 'AbortError') {
167
+ if (req.aborted || !res.writableEnded || err.name === 'AbortError') {
166
168
  reqLogger.debug('request aborted')
167
169
  } else if (err.statusCode < 500) {
168
170
  reqLogger.warn('request failed')
@@ -179,6 +181,8 @@ module.exports.request = async function request(ctx, next) {
179
181
  }
180
182
 
181
183
  ac.abort(err)
184
+ } finally {
185
+ res.destroy()
182
186
  }
183
187
  }
184
188
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "15.0.53",
3
+ "version": "15.0.55",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "files": [
@@ -81,7 +81,7 @@
81
81
  "lodash": "^4.17.21",
82
82
  "mime": "^3.0.0",
83
83
  "moment-timezone": "^0.5.43",
84
- "nconf": "^0.12.0",
84
+ "nconf": "^0.12.1",
85
85
  "nested-error-stacks": "^2.1.1",
86
86
  "object-hash": "^3.0.0",
87
87
  "pino-std-serializers": "^6.2.2",
@@ -90,25 +90,25 @@
90
90
  "smpte-timecode": "^1.3.3",
91
91
  "split-string": "^6.0.0",
92
92
  "toobusy-js": "^0.5.1",
93
- "undici": "^5.25.4",
93
+ "undici": "^5.27.1",
94
94
  "url-join": "^4.0.0"
95
95
  },
96
96
  "devDependencies": {
97
- "@types/node": "^20.8.2",
98
- "eslint": "^8.50.0",
97
+ "@types/node": "^20.8.10",
98
+ "eslint": "^8.52.0",
99
99
  "eslint-config-prettier": "^9.0.0",
100
100
  "eslint-config-standard": "^17.0.0",
101
- "eslint-plugin-import": "^2.28.1",
102
- "eslint-plugin-n": "^16.1.0",
101
+ "eslint-plugin-import": "^2.29.0",
102
+ "eslint-plugin-n": "^16.2.0",
103
103
  "eslint-plugin-node": "^11.1.0",
104
104
  "eslint-plugin-promise": "^6.0.0",
105
105
  "husky": "^8.0.3",
106
- "lint-staged": "^14.0.1",
106
+ "lint-staged": "^15.0.2",
107
107
  "pinst": "^3.0.0",
108
108
  "prettier": "^3.0.3",
109
109
  "rxjs": "^7.5.6",
110
110
  "send": "^0.18.0",
111
- "tap": "^18.4.2"
111
+ "tap": "^18.5.6"
112
112
  },
113
113
  "peerDependencies": {
114
114
  "@elastic/elasticsearch": "^8.6.0",