@nxtedition/lib 14.1.0 → 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 +1 -1
  2. package/undici.js +102 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "14.1.0",
3
+ "version": "14.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "files": [
package/undici.js CHANGED
@@ -1,29 +1,114 @@
1
- import * as undici from 'undici'
2
- import xuid from 'xuid'
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')
3
7
 
4
- export async function request(url, { logger, ...options }) {
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
+ ) {
5
23
  const ureq = {
6
24
  url,
7
- maxRedirections: 3,
25
+ method,
26
+ body,
8
27
  headers: {
9
- 'req-id': xuid(),
10
- 'user-agent': options.userAgent,
11
- ...options.headers,
28
+ 'req-id': id,
29
+ 'user-agent': userAgent,
30
+ ...headers,
12
31
  },
13
- ...options,
14
- throwOnError: true,
15
32
  }
16
33
 
17
- logger?.debug({ ureq }, 'upstream request started')
34
+ const upstreamLogger = logger?.child({ ureq })
18
35
 
19
- const ures = await undici.request(url, options)
36
+ upstreamLogger?.debug({ ureq }, 'upstream request started')
20
37
 
21
- logger?.debug({ ureq, ures }, 'upstream request response')
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
+ })
22
51
 
23
- if (ures.statusCode >= 300 && ures.statusCode < 400) {
24
- await ures.body.dump()
25
- throw new Error('maxRedirections exceeded')
26
- }
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
+ }
27
68
 
28
- return ures
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
+ }
29
114
  }