@nxtedition/lib 15.0.52 → 15.0.54
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.
- package/http.js +44 -39
- package/merge-ranges.js +23 -8
- 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,31 @@ 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
|
+
this[kResolve](null)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function onResponseError(err) {
|
|
42
|
+
this.log.error({ err }, 'response error')
|
|
43
|
+
this[kResolve](Promise.reject(err))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function onResponseClose() {
|
|
47
|
+
this.log.debug('response closed')
|
|
48
|
+
this[kResolve](null)
|
|
49
|
+
}
|
|
50
|
+
|
|
27
51
|
module.exports.request = async function request(ctx, next) {
|
|
28
52
|
const { req, res, logger } = ctx
|
|
29
53
|
const startTime = performance.now()
|
|
@@ -39,10 +63,10 @@ module.exports.request = async function request(ctx, next) {
|
|
|
39
63
|
}
|
|
40
64
|
|
|
41
65
|
ctx.id = req.id = req.headers['request-id'] || genReqId()
|
|
42
|
-
ctx.logger = req.log = logger.child({ req })
|
|
66
|
+
ctx.logger = req.log = res.log = logger.child({ req })
|
|
43
67
|
ctx.signal = signal
|
|
44
68
|
ctx.method = req.method
|
|
45
|
-
ctx.query = ctx.url.search ? querystring.parse(ctx.url.search.slice(1)) : {}
|
|
69
|
+
ctx.query = ctx.url.search.length > 1 ? querystring.parse(ctx.url.search.slice(1)) : {}
|
|
46
70
|
|
|
47
71
|
if (req.method === 'GET' || req.method === 'HEAD') {
|
|
48
72
|
req.resume() // Dump the body if there is one.
|
|
@@ -54,55 +78,34 @@ module.exports.request = async function request(ctx, next) {
|
|
|
54
78
|
|
|
55
79
|
reqLogger = ctx.logger
|
|
56
80
|
if (!isHealthcheck) {
|
|
57
|
-
reqLogger.debug(
|
|
81
|
+
reqLogger.debug('request started')
|
|
58
82
|
} else {
|
|
59
|
-
reqLogger.trace(
|
|
83
|
+
reqLogger.trace('request started')
|
|
60
84
|
}
|
|
61
85
|
|
|
62
86
|
await Promise.all([
|
|
63
87
|
next(),
|
|
64
|
-
new Promise((resolve
|
|
65
|
-
res
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
})
|
|
88
|
+
new Promise((resolve) => {
|
|
89
|
+
res[kResolve] = resolve
|
|
90
|
+
|
|
91
|
+
res.on('timeout', onTimeout).on('error', onResponseError).on('close', onResponseClose)
|
|
92
|
+
|
|
93
|
+
req.on('timeout', onTimeout).on('error', onRequestError).on('close', onRequestClose)
|
|
87
94
|
}),
|
|
88
95
|
])
|
|
89
96
|
|
|
90
|
-
assert(req.aborted || res.writableEnded)
|
|
91
|
-
|
|
92
97
|
const responseTime = Math.round(performance.now() - startTime)
|
|
93
98
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (req.aborted) {
|
|
97
|
-
reqLogger.debug('request aborted')
|
|
99
|
+
if (!res.writableEnded) {
|
|
100
|
+
reqLogger.debug({ res, responseTime }, 'request aborted')
|
|
98
101
|
} else if (res.statusCode >= 500) {
|
|
99
|
-
reqLogger.error('request error')
|
|
102
|
+
reqLogger.error({ res, responseTime }, 'request error')
|
|
100
103
|
} else if (res.statusCode >= 400) {
|
|
101
|
-
reqLogger.warn('request failed')
|
|
104
|
+
reqLogger.warn({ res, responseTime }, 'request failed')
|
|
102
105
|
} else if (!isHealthcheck) {
|
|
103
|
-
reqLogger.debug('request completed')
|
|
106
|
+
reqLogger.debug({ res, responseTime }, 'request completed')
|
|
104
107
|
} else {
|
|
105
|
-
reqLogger.trace('request completed')
|
|
108
|
+
reqLogger.trace({ res, responseTime }, 'request completed')
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
ac.abort()
|
|
@@ -162,7 +165,7 @@ module.exports.request = async function request(ctx, next) {
|
|
|
162
165
|
} else {
|
|
163
166
|
reqLogger = reqLogger.child({ res, err, reason, responseTime })
|
|
164
167
|
|
|
165
|
-
if (req.aborted || err.name === 'AbortError') {
|
|
168
|
+
if (req.aborted || !res.writableEnded || err.name === 'AbortError') {
|
|
166
169
|
reqLogger.debug('request aborted')
|
|
167
170
|
} else if (err.statusCode < 500) {
|
|
168
171
|
reqLogger.warn('request failed')
|
|
@@ -179,6 +182,8 @@ module.exports.request = async function request(ctx, next) {
|
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
ac.abort(err)
|
|
185
|
+
} finally {
|
|
186
|
+
res.destroy()
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
189
|
|
package/merge-ranges.js
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
|
+
const EMPTY_ARR = Object.freeze([])
|
|
2
|
+
|
|
1
3
|
module.exports = function mergeRanges(ranges) {
|
|
2
4
|
if (!Array.isArray(ranges)) {
|
|
3
|
-
return
|
|
5
|
+
return EMPTY_ARR
|
|
4
6
|
}
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
if (ranges.length === 1) {
|
|
9
|
+
const range = ranges[0]
|
|
10
|
+
return Array.isArray(range) && range.length === 2 && range[1] > range[0] ? ranges : EMPTY_ARR
|
|
11
|
+
}
|
|
7
12
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
{
|
|
14
|
+
// Make sure ranges are valid and copied for mutation.
|
|
15
|
+
const tmp = []
|
|
16
|
+
for (let n = 0, len = ranges.length; n < len; n++) {
|
|
17
|
+
const range = ranges[n]
|
|
18
|
+
if (Array.isArray(range) && range.length === 2 && range[1] > range[0]) {
|
|
19
|
+
tmp.push([range[0], range[1]])
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
ranges = tmp
|
|
23
|
+
}
|
|
11
24
|
|
|
12
|
-
if (
|
|
13
|
-
return
|
|
25
|
+
if (ranges.length <= 1) {
|
|
26
|
+
return ranges
|
|
14
27
|
}
|
|
15
28
|
|
|
16
|
-
ranges
|
|
29
|
+
ranges.sort((a, b) => a[0] - b[0])
|
|
30
|
+
|
|
31
|
+
const stack = []
|
|
17
32
|
|
|
18
33
|
// Add first range to stack
|
|
19
34
|
stack.push(ranges[0])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.54",
|
|
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.
|
|
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.
|
|
93
|
+
"undici": "^5.27.1",
|
|
94
94
|
"url-join": "^4.0.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@types/node": "^20.8.
|
|
98
|
-
"eslint": "^8.
|
|
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.
|
|
102
|
-
"eslint-plugin-n": "^16.
|
|
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": "^
|
|
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.
|
|
111
|
+
"tap": "^18.5.6"
|
|
112
112
|
},
|
|
113
113
|
"peerDependencies": {
|
|
114
114
|
"@elastic/elasticsearch": "^8.6.0",
|