@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.
- package/lib/interceptor/cache.js +35 -2
- package/lib/interceptor/dns.js +23 -5
- package/lib/utils.js +4 -0
- package/package.json +1 -1
package/lib/interceptor/cache.js
CHANGED
|
@@ -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
|
+
}
|
package/lib/interceptor/dns.js
CHANGED
|
@@ -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
|
}
|