@nxtedition/nxt-undici 7.3.14 → 7.3.15

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.
@@ -45,14 +45,19 @@ export default () => (dispatch) => {
45
45
  resolve([err, null])
46
46
  } else {
47
47
  const now = getFastNow()
48
- const val = records.map(({ address }) => ({
49
- address,
50
- expires: now + (ttl ?? 1e3),
51
- pending: 0,
52
- errored: 0,
53
- counter: 0,
54
- timeout: 0,
55
- }))
48
+ const prev = cache.get(hostname)
49
+ const prevByAddr = prev ? new Map(prev.map((r) => [r.address, r])) : null
50
+ const val = records.map(({ address }) => {
51
+ const old = prevByAddr?.get(address)
52
+ return {
53
+ address,
54
+ expires: now + (ttl ?? 1e3),
55
+ pending: 0,
56
+ errored: old ? old.errored : 0,
57
+ counter: 0,
58
+ timeout: old ? old.timeout : 0,
59
+ }
60
+ })
56
61
 
57
62
  cache.set(hostname, val)
58
63
 
@@ -173,8 +173,7 @@ export default () => (dispatch) => (opts, handler) => {
173
173
  // the request message does not contain a payload body and the method
174
174
  // semantics do not anticipate such a body.
175
175
  // undici will error if provided an unexpected content-length: 0 header.
176
- }
177
- if (key[0] === ':') {
176
+ } else if (key[0] === ':') {
178
177
  // strip pseudo headers
179
178
  } else if (key === 'expect') {
180
179
  // undici doesn't support expect header.
@@ -176,11 +176,10 @@ function shouldRemoveHeader(header, removeContent, unknownOrigin) {
176
176
 
177
177
  // https://tools.ietf.org/html/rfc7231#section-6.4
178
178
  function cleanRequestHeaders(headers, removeContent, unknownOrigin) {
179
- let ret
179
+ const ret = {}
180
180
  if (headers && typeof headers === 'object') {
181
181
  for (const key of Object.keys(headers)) {
182
182
  if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) {
183
- ret ??= {}
184
183
  ret[key] = headers[key]
185
184
  }
186
185
  }
@@ -1,11 +1,14 @@
1
1
  import { DecoratorHandler, decorateError } from '../utils.js'
2
2
 
3
+ const MAX_ERROR_BODY_SIZE = 256 * 1024
4
+
3
5
  class Handler extends DecoratorHandler {
4
6
  #statusCode = 0
5
7
  #decoder
6
8
  #headers
7
9
  #trailers
8
10
  #body = ''
11
+ #bodySize = 0
9
12
  #opts
10
13
 
11
14
  constructor(opts, { handler }) {
@@ -19,6 +22,7 @@ class Handler extends DecoratorHandler {
19
22
  this.#decoder = null
20
23
  this.#headers = null
21
24
  this.#body = ''
25
+ this.#bodySize = 0
22
26
 
23
27
  super.onConnect(abort)
24
28
  }
@@ -45,7 +49,12 @@ class Handler extends DecoratorHandler {
45
49
  return super.onData(chunk)
46
50
  }
47
51
 
48
- this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? ''
52
+ if (this.#decoder) {
53
+ this.#bodySize += chunk.byteLength
54
+ if (this.#bodySize <= MAX_ERROR_BODY_SIZE) {
55
+ this.#body += this.#decoder.decode(chunk, { stream: true })
56
+ }
57
+ }
49
58
  }
50
59
 
51
60
  onComplete(trailers) {
@@ -85,6 +85,10 @@ class Handler extends DecoratorHandler {
85
85
  this.#statusCode = statusCode
86
86
  this.#headers = headers
87
87
 
88
+ if (statusCode < 200) {
89
+ return super.onHeaders(statusCode, headers, resume)
90
+ }
91
+
88
92
  if (!this.#headersSent) {
89
93
  assert(this.#etag == null)
90
94
  assert(this.#pos == null)
@@ -232,6 +236,14 @@ class Handler extends DecoratorHandler {
232
236
  }
233
237
 
234
238
  super.onComplete(this.#trailers)
239
+ } else {
240
+ // Headers already sent but retry failed (e.g. etag mismatch, missing
241
+ // content-range). The user is waiting for data/complete — send an error
242
+ // so the response stream doesn't hang.
243
+ if (!this.#errorSent) {
244
+ this.#errorSent = true
245
+ super.onError(new Error('Response retry failed'))
246
+ }
235
247
  }
236
248
 
237
249
  this.#maybeAbort(err)
@@ -1,5 +1,4 @@
1
1
  import crypto from 'node:crypto'
2
- import assert from 'node:assert'
3
2
  import { DecoratorHandler } from '../utils.js'
4
3
 
5
4
  class Handler extends DecoratorHandler {
@@ -16,8 +15,6 @@ class Handler extends DecoratorHandler {
16
15
  }
17
16
 
18
17
  onConnect(abort) {
19
- assert(!this.#pos)
20
-
21
18
  this.#contentMD5 = null
22
19
  this.#contentLength = null
23
20
  this.#hasher = null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/nxt-undici",
3
- "version": "7.3.14",
3
+ "version": "7.3.15",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "main": "lib/index.js",