@nxtedition/nxt-undici 6.1.7 → 6.2.0

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.
@@ -95,7 +95,6 @@ class CacheHandler extends DecoratorHandler {
95
95
  }
96
96
 
97
97
  const cachedAt = Date.now()
98
-
99
98
  this.#value = {
100
99
  body: [],
101
100
  size: 0,
@@ -104,7 +103,7 @@ class CacheHandler extends DecoratorHandler {
104
103
  statusMessage: '',
105
104
  headers,
106
105
  cacheControlDirectives,
107
- etag: headers.etag,
106
+ etag: typeof headers.etag === 'string' && isEtagUsable(headers.etag) ? headers.etag : '',
108
107
  vary,
109
108
  cachedAt,
110
109
  staleAt: 0,
@@ -213,3 +212,37 @@ export default () => (dispatch) => (opts, handler) => {
213
212
  abort(err)
214
213
  }
215
214
  }
215
+
216
+ /**
217
+ * Note: this deviates from the spec a little. Empty etags ("", W/"") are valid,
218
+ * however, including them in cached resposnes serves little to no purpose.
219
+ *
220
+ * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-etag
221
+ *
222
+ * @param {string} etag
223
+ * @returns {boolean}
224
+ */
225
+ function isEtagUsable(etag) {
226
+ if (etag.length <= 2) {
227
+ // Shortest an etag can be is two chars (just ""). This is where we deviate
228
+ // from the spec requiring a min of 3 chars however
229
+ return false
230
+ }
231
+
232
+ if (etag[0] === '"' && etag[etag.length - 1] === '"') {
233
+ // ETag: ""asd123"" or ETag: "W/"asd123"", kinda undefined behavior in the
234
+ // spec. Some servers will accept these while others don't.
235
+ // ETag: "asd123"
236
+ return !(etag[1] === '"' || etag.startsWith('"W/'))
237
+ }
238
+
239
+ if (etag.startsWith('W/"') && etag[etag.length - 1] === '"') {
240
+ // ETag: W/"", also where we deviate from the spec & require a min of 3
241
+ // chars
242
+ // ETag: for W/"", W/"asd123"
243
+ return etag.length !== 4
244
+ }
245
+
246
+ // Anything else
247
+ return false
248
+ }
@@ -28,11 +28,28 @@ class Handler extends DecoratorHandler {
28
28
  }
29
29
  }
30
30
 
31
+ class DefaultCache {
32
+ #map = new Map()
33
+
34
+ set(hostname, records) {
35
+ this.#map.set(hostname, records)
36
+ }
37
+
38
+ get(hostname) {
39
+ return this.#map.get(hostname)
40
+ }
41
+
42
+ delete(hostname) {
43
+ this.#map.delete(hostname)
44
+ }
45
+ }
46
+
47
+ const DEFAULT_CACHE = new DefaultCache()
48
+
31
49
  export default () => (dispatch) => {
32
- const cache = new Map()
33
50
  const promises = new Map()
34
51
 
35
- function resolve(hostname, { resolve4, logger }) {
52
+ function resolve(hostname, { cache, resolve4, logger }) {
36
53
  let promise = promises.get(hostname)
37
54
  if (!promise) {
38
55
  logger?.debug({ dns: { hostname } }, 'lookup started')
@@ -51,7 +68,7 @@ export default () => (dispatch) => {
51
68
  counter: 0,
52
69
  }))
53
70
 
54
- logger?.debug({ err, dns: { records } }, 'lookup completed')
71
+ logger?.debug({ err, dns: { hostname, records } }, 'lookup completed')
55
72
 
56
73
  cache.set(hostname, val)
57
74
 
@@ -79,6 +96,7 @@ export default () => (dispatch) => {
79
96
 
80
97
  try {
81
98
  const { host, hostname } = origin
99
+ const cache = opts.dns.cache ?? DEFAULT_CACHE
82
100
 
83
101
  const now = getFastNow()
84
102
 
@@ -88,7 +106,7 @@ export default () => (dispatch) => {
88
106
  const logger = opts.dns.logger ?? opts.logger
89
107
 
90
108
  if (records == null || records.every((x) => x.expires < now)) {
91
- const [err, val] = await resolve(hostname, { resolve4, logger })
109
+ const [err, val] = await resolve(hostname, { cache, resolve4, logger })
92
110
 
93
111
  if (err) {
94
112
  throw err
@@ -98,7 +116,7 @@ export default () => (dispatch) => {
98
116
 
99
117
  records = val
100
118
  } else if (records.some((x) => x.expires < now + 1e3)) {
101
- resolve(hostname, { resolve4, logger })
119
+ resolve(hostname, { cache, resolve4, logger })
102
120
  }
103
121
 
104
122
  records.sort(
package/lib/utils.js CHANGED
@@ -248,6 +248,10 @@ export class DecoratorHandler {
248
248
 
249
249
  onComplete(trailers) {
250
250
  if (!this.#aborted && !this.#completed && !this.#errored) {
251
+ <<<<<<< HEAD
252
+ this.#abort = null
253
+ =======
254
+ >>>>>>> 23823e3 (fix: decoerator)
251
255
  this.#completed = true
252
256
  return this.#handler.onComplete?.(trailers)
253
257
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/nxt-undici",
3
- "version": "6.1.7",
3
+ "version": "6.2.0",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "main": "lib/index.js",