Skip to content

Commit e840cfd

Browse files
authored
Merge branch 'main' into sqlite
2 parents b3c932e + 866794e commit e840cfd

13 files changed

+145
-79
lines changed

.husky/pre-commit

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
#!/bin/sh
2-
. "$(dirname "$0")/_/husky.sh"
3-
yarn lint-staged
1+
npx lint-staged

lib/index.js

+10-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import undici from '@nxtedition/undici'
1+
import undici from 'undici'
22
import { parseHeaders } from './utils.js'
33

44
const dispatcherCache = new WeakMap()
@@ -18,7 +18,11 @@ export const interceptors = {
1818
}
1919

2020
export { parseHeaders } from './utils.js'
21-
export { Client, Pool, Agent, getGlobalDispatcher, setGlobalDispatcher } from '@nxtedition/undici'
21+
export { Client, Pool, Agent, getGlobalDispatcher, setGlobalDispatcher } from 'undici'
22+
23+
function defaultLookup(origin, opts, callback) {
24+
callback(null, Array.isArray(origin) ? origin[Math.floor(Math.random() * origin.length)] : origin)
25+
}
2226

2327
function wrapDispatcher(dispatcher) {
2428
let wrappedDispatcher = dispatcherCache.get(dispatcher)
@@ -60,24 +64,18 @@ function wrapDispatcher(dispatcher) {
6064
headersTimeout: opts.headersTimeout,
6165
bodyTimeout: opts.bodyTimeout,
6266
idempotent: opts.idempotent,
63-
retry: opts.retry ?? 8,
67+
retry: opts.retry ?? 4,
6468
proxy: opts.proxy ?? false,
6569
cache: opts.cache ?? false,
6670
upgrade: opts.upgrade ?? false,
6771
follow: opts.follow ?? 8,
6872
error: opts.error ?? true,
6973
verify: opts.verify ?? true,
7074
logger: opts.logger ?? null,
71-
lookup:
72-
opts.lookup ??
73-
((origin, opts, callback) =>
74-
callback(
75-
null,
76-
Array.isArray(origin)
77-
? origin[Math.floor(Math.random() * origin.length)]
78-
: origin,
79-
)),
8075
dns: opts.dns ?? true,
76+
connect: opts.connect,
77+
lookup: opts.lookup ?? defaultLookup,
78+
maxRedirections: 0, // TODO (fix): Ugly hack to disable undici redirections.
8179
},
8280
handler,
8381
)

lib/interceptor/dns.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,26 @@ export default (interceptorOpts) => (dispatch) => (opts, handler) => {
5757

5858
assert(typeof resolver.lookup === 'function')
5959

60-
const { hostname } = new URL(opts.origin)
60+
const { hostname, host } = new URL(opts.origin)
6161

62-
if (net.isIP(hostname)) {
62+
if (net.isIP(hostname) || opts.headers?.host) {
6363
return dispatch(opts, handler)
6464
}
6565

6666
const callback = (err, val) => {
6767
if (err) {
68-
handler.onConnect(() => {})
6968
handler.onError(err)
7069
} else {
7170
const url = new URL(opts.origin)
7271
url.hostname = Array.isArray(val)
7372
? val[Math.floor(val.length * Math.random())].address
7473
: val?.address ?? val
7574
dispatch(
76-
{ ...opts, origin: url.origin },
75+
{
76+
...opts,
77+
origin: url.origin,
78+
headers: { ...opts.headers, host },
79+
},
7780
resolver.clear ? new Handler({ resolver, key: hostname }, { handler }) : handler,
7881
)
7982
}
@@ -88,7 +91,6 @@ export default (interceptorOpts) => (dispatch) => (opts, handler) => {
8891
)
8992
}
9093
} catch (err) {
91-
handler.onConnect(() => {})
9294
handler.onError(err)
9395
}
9496

lib/interceptor/log.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { DecoratorHandler, parseHeaders } from '../utils.js'
33
class Handler extends DecoratorHandler {
44
#handler
55
#opts
6-
#abort
7-
#aborted = false
86
#logger
9-
#pos
7+
8+
#abort = null
9+
#aborted = false
10+
#pos = 0
1011
#timing = {
1112
created: performance.now(),
1213
connect: -1,

lib/interceptor/lookup.js

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export default (opts) => (dispatch) => (opts, handler) => {
77

88
const callback = (err, origin) => {
99
if (err) {
10-
handler.onConnect(() => {})
1110
handler.onError(err)
1211
} else {
1312
dispatch({ ...opts, origin }, handler)

lib/interceptor/redirect.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
66
class Handler extends DecoratorHandler {
77
#dispatch
88
#handler
9-
109
#opts
11-
#abort
12-
#aborted = false
13-
#reason
1410
#maxCount
11+
12+
#abort = null
13+
#aborted = false
14+
#reason = null
1515
#headersSent = false
1616
#count = 0
17-
#location
17+
#location = null
1818
#history = []
1919

2020
constructor(opts, { dispatch, handler }) {

lib/interceptor/request-body-factory.js

-2
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ export default (opts) => (dispatch) => (opts, handler) => {
1212
dispatch({ ...opts, body }, handler)
1313
})
1414
.catch((err) => {
15-
handler.onConnect(() => {})
1615
handler.onError(err)
1716
})
1817
return true
1918
} else {
2019
return dispatch({ ...opts, body }, handler)
2120
}
2221
} catch (err) {
23-
handler.onConnect(() => {})
2422
handler.onError(err)
2523
return true
2624
}

lib/interceptor/response-error.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import { DecoratorHandler, parseHeaders } from '../utils.js'
44
class Handler extends DecoratorHandler {
55
#handler
66

7-
#statusCode
8-
#contentType
9-
#decoder
10-
#headers
11-
#body
12-
#errored
7+
#statusCode = 0
8+
#contentType = null
9+
#decoder = null
10+
#headers = null
11+
#body = ''
12+
#opts
13+
#errored = false
1314

1415
constructor(opts, { handler }) {
1516
super(handler)
1617

18+
this.#opts = opts
1719
this.#handler = handler
1820
}
1921

@@ -71,6 +73,7 @@ class Handler extends DecoratorHandler {
7173
Error.stackTraceLimit = 0
7274
try {
7375
err = Object.assign(createHttpError(this.#statusCode), {
76+
url: new URL(this.#opts.path, this.#opts.origin).href,
7477
reason: this.#body?.reason,
7578
error: this.#body?.error,
7679
headers: this.#headers,

lib/interceptor/response-retry.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ class Handler extends DecoratorHandler {
1717
#headersSent = false
1818
#errorSent = false
1919

20-
#abort
20+
#abort = null
2121
#aborted = false
2222
#reason = null
2323

24-
#pos
25-
#end
26-
#etag
27-
#error
24+
#pos = null
25+
#end = null
26+
#etag = null
27+
#error = null
2828

2929
constructor(opts, { handler, dispatch }) {
3030
super(handler)

lib/interceptor/response-verify.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ class Handler extends DecoratorHandler {
88
#handler
99

1010
#verifyOpts
11-
#contentMD5
12-
#contentLength
13-
#hasher
14-
#pos
15-
#errored
11+
#contentMD5 = null
12+
#contentLength = null
13+
#hasher = null
14+
#pos = 0
15+
#errored = false
1616

1717
constructor(opts, { handler }) {
1818
super(handler)
@@ -74,9 +74,7 @@ class Handler extends DecoratorHandler {
7474
}
7575

7676
onError(err) {
77-
if (this.#errored) {
78-
// Do nothing...
79-
} else {
77+
if (!this.#errored) {
8078
this.#handler.onError(err)
8179
}
8280
}

lib/utils.js

+87-18
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import tp from 'node:timers/promises'
22
import cacheControlParser from 'cache-control-parser'
33
import stream from 'node:stream'
4-
import { util } from '@nxtedition/undici'
5-
6-
const noop = () => {}
4+
import { util } from 'undici'
75

86
export function parseCacheControl(str) {
97
return str ? cacheControlParser.parse(str) : null
@@ -196,15 +194,6 @@ export function parseOrigin(url) {
196194
return url
197195
}
198196

199-
/**
200-
* @param {Record<string, string | string[] | null | undefined> | (Buffer | string | (Buffer | string)[])[]} headers
201-
* @param {Record<string, string | string[]>} [obj]
202-
* @returns {Record<string, string | string[]>}
203-
*/
204-
export function parseHeaders(headers, obj) {
205-
return util.parseHeaders(headers, obj)
206-
}
207-
208197
export class AbortError extends Error {
209198
constructor(message) {
210199
super(message ?? 'The operation was aborted')
@@ -252,7 +241,6 @@ export function bodyLength(body) {
252241

253242
export class DecoratorHandler {
254243
#handler
255-
#onConnectCalled = false
256244

257245
constructor(handler) {
258246
if (typeof handler !== 'object' || handler === null) {
@@ -262,15 +250,10 @@ export class DecoratorHandler {
262250
}
263251

264252
onConnect(...args) {
265-
this.#onConnectCalled = true
266253
return this.#handler.onConnect?.(...args)
267254
}
268255

269256
onError(...args) {
270-
if (!this.#onConnectCalled) {
271-
this.#onConnectCalled = true
272-
this.#handler.onConnect?.(noop)
273-
}
274257
return this.#handler.onError?.(...args)
275258
}
276259

@@ -298,3 +281,89 @@ export class DecoratorHandler {
298281
return this.#handler.onBodySent?.(...args)
299282
}
300283
}
284+
285+
/**
286+
* @param {Record<string, string | string[] | null | undefined> | (Buffer | string | (Buffer | string)[])[]} headers
287+
* @param {Record<string, string | string[]>} [obj]
288+
* @returns {Record<string, string | string[]>}
289+
*/
290+
export function parseHeaders(headers, obj) {
291+
if (obj == null) {
292+
obj = {}
293+
} else {
294+
// TODO (fix): assert obj values type?
295+
}
296+
297+
if (Array.isArray(headers)) {
298+
for (let i = 0; i < headers.length; i += 2) {
299+
const key2 = headers[i]
300+
const val2 = headers[i + 1]
301+
302+
// TODO (fix): assert key2 type?
303+
// TODO (fix): assert val2 type?
304+
305+
if (val2 == null) {
306+
continue
307+
}
308+
309+
const key = util.headerNameToString(key2)
310+
let val = obj[key]
311+
312+
if (val) {
313+
if (!Array.isArray(val)) {
314+
val = [val]
315+
obj[key] = val
316+
}
317+
318+
if (Array.isArray(val2)) {
319+
val.push(...val2.filter((x) => x != null).map((x) => `${x}`))
320+
} else {
321+
val.push(`${val2}`)
322+
}
323+
} else {
324+
obj[key] = Array.isArray(val2)
325+
? val2.filter((x) => x != null).map((x) => `${x}`)
326+
: `${val2}`
327+
}
328+
}
329+
} else if (typeof headers === 'object' && headers !== null) {
330+
for (const key2 of Object.keys(headers)) {
331+
const val2 = headers[key2]
332+
333+
// TODO (fix): assert key2 type?
334+
// TODO (fix): assert val2 type?
335+
336+
if (val2 == null) {
337+
continue
338+
}
339+
340+
const key = util.headerNameToString(key2)
341+
let val = obj[key]
342+
343+
if (val) {
344+
if (!Array.isArray(val)) {
345+
val = [val]
346+
obj[key] = val
347+
}
348+
if (Array.isArray(val2)) {
349+
val.push(...val2.filter((x) => x != null).map((x) => `${x}`))
350+
} else {
351+
val.push(`${val2}`)
352+
}
353+
} else if (val2 != null) {
354+
obj[key] = Array.isArray(val2)
355+
? val2.filter((x) => x != null).map((x) => `${x}`)
356+
: `${val2}`
357+
}
358+
}
359+
} else if (headers != null) {
360+
throw new Error('invalid argument: headers')
361+
}
362+
363+
// See https://github.com/nodejs/node/pull/46528
364+
if ('content-length' in obj && 'content-disposition' in obj) {
365+
obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1')
366+
}
367+
368+
return obj
369+
}

0 commit comments

Comments
 (0)