@nxtedition/lib 14.0.27 → 14.1.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.
Files changed (2) hide show
  1. package/package.json +4 -3
  2. package/undici.js +114 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "14.0.27",
3
+ "version": "14.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "files": [
@@ -23,6 +23,7 @@
23
23
  "errors.js",
24
24
  "worker.js",
25
25
  "proxy.js",
26
+ "undici.js",
26
27
  "timeline.js",
27
28
  "docker-secrets.js"
28
29
  ],
@@ -72,7 +73,6 @@
72
73
  "date-fns": "^2.29.3",
73
74
  "fast-querystring": "^1.1.1",
74
75
  "hasha": "^5.2.2",
75
- "http-errors": "^2.0.0",
76
76
  "json5": "^2.2.3",
77
77
  "koa-compose": "^4.1.0",
78
78
  "lodash": "^4.17.21",
@@ -88,7 +88,8 @@
88
88
  "split-string": "^6.0.0",
89
89
  "toobusy-js": "^0.5.1",
90
90
  "undici": "^5.22.0",
91
- "url-join": "^4.0.0"
91
+ "url-join": "^4.0.0",
92
+ "xuid": "^4.1.2"
92
93
  },
93
94
  "devDependencies": {
94
95
  "eslint": "^8.38.0",
package/undici.js ADDED
@@ -0,0 +1,114 @@
1
+ const assert = require('assert')
2
+ const tp = require('timers/promises')
3
+ const xuid = require('xuid')
4
+ const { isReadableNodeStream } = require('./stream')
5
+ const undici = require('undici')
6
+ const stream = require('stream')
7
+
8
+ module.exports.request = async function request(
9
+ url,
10
+ {
11
+ logger,
12
+ id = xuid(),
13
+ retry: { count: maxRetries = 8 } = {},
14
+ redirect: { count: maxRedirections = 3 } = {},
15
+ dispatcher,
16
+ signal,
17
+ method = 'GET',
18
+ body,
19
+ userAgent,
20
+ headers,
21
+ }
22
+ ) {
23
+ const ureq = {
24
+ url,
25
+ method,
26
+ body,
27
+ headers: {
28
+ 'req-id': id,
29
+ 'user-agent': userAgent,
30
+ ...headers,
31
+ },
32
+ }
33
+
34
+ const upstreamLogger = logger?.child({ ureq })
35
+
36
+ upstreamLogger?.debug({ ureq }, 'upstream request started')
37
+
38
+ try {
39
+ /* eslint-disable no-unreachable-loop */
40
+ for (let retryCount = 0; true; retryCount++) {
41
+ try {
42
+ const ures = await undici.request(url, {
43
+ method,
44
+ body,
45
+ headers,
46
+ signal,
47
+ dispatcher,
48
+ maxRedirections,
49
+ throwOnError: true,
50
+ })
51
+
52
+ upstreamLogger?.debug({ ureq, ures }, 'upstream request response')
53
+
54
+ if (ures.statusCode >= 300 && ures.statusCode < 400) {
55
+ await ures.body.dump()
56
+ throw new Error('maxRedirections exceeded')
57
+ }
58
+
59
+ assert(ures.statusCode >= 200 && ures.statusCode < 300)
60
+
61
+ // TODO (fix): Wrap response to handle error that can continue with range request...
62
+
63
+ return ures
64
+ } catch (err) {
65
+ if (retryCount >= maxRetries) {
66
+ throw err
67
+ }
68
+
69
+ if (
70
+ body != null &&
71
+ typeof body !== 'string' &&
72
+ !Buffer.isBuffer(body) &&
73
+ (!isReadableNodeStream(body) || stream.isDisturbed(body))
74
+ ) {
75
+ throw err
76
+ }
77
+
78
+ if (method === 'HEAD' || method === 'GET') {
79
+ if (
80
+ err.code !== 'ECONNRESET' &&
81
+ err.code !== 'ECONNREFUSED' &&
82
+ err.code !== 'ENOTFOUND' &&
83
+ err.code !== 'ENETDOWN' &&
84
+ err.code !== 'ENETUNREACH' &&
85
+ err.code !== 'EHOSTDOWN' &&
86
+ err.code !== 'EHOSTUNREACH' &&
87
+ err.code !== 'EPIPE' &&
88
+ err.message !== 'other side closed' &&
89
+ err.statusCode !== 420 &&
90
+ err.statusCode !== 429 &&
91
+ err.statusCode !== 502 &&
92
+ err.statusCode !== 503 &&
93
+ err.statusCode !== 504
94
+ ) {
95
+ throw err
96
+ }
97
+ } else {
98
+ // TODO (fix): What to do?
99
+ throw err
100
+ }
101
+
102
+ const delay =
103
+ parseInt(err.headers?.['Retry-After']) * 1e3 || Math.min(10e3, retryCount * 1e3 + 1e3)
104
+
105
+ logger?.warn({ err, retryCount, delay }, 'upstream request retrying')
106
+
107
+ return tp.setTimeout(delay, undefined, { signal })
108
+ }
109
+ }
110
+ } catch (err) {
111
+ logger?.error({ err }, 'upstream request failed')
112
+ throw err
113
+ }
114
+ }