@nxtedition/nxt-undici 3.3.0 → 3.3.2

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/index.js CHANGED
@@ -20,7 +20,7 @@ export const interceptors = {
20
20
  export { parseHeaders } from './utils.js'
21
21
  export { Client, Pool, Agent, getGlobalDispatcher, setGlobalDispatcher } from '@nxtedition/undici'
22
22
 
23
- function wrapdDispatcher(dispatcher) {
23
+ function wrapDispatcher(dispatcher) {
24
24
  let wrappedDispatcher = dispatcherCache.get(dispatcher)
25
25
  if (wrappedDispatcher == null) {
26
26
  wrappedDispatcher = dispatcher.compose(
@@ -35,6 +35,45 @@ function wrapdDispatcher(dispatcher) {
35
35
  interceptors.redirect(),
36
36
  interceptors.cache(),
37
37
  interceptors.proxy(),
38
+ (dispatch) => (opts, handler) => {
39
+ const headers = parseHeaders(opts.headers)
40
+
41
+ const userAgent = opts.userAgent ?? globalThis.userAgent
42
+ if (userAgent && headers?.['user-agent'] !== userAgent) {
43
+ headers['user-agent'] = userAgent
44
+ }
45
+
46
+ const url = opts.url ? new URL(opts.url) : null
47
+
48
+ return dispatch(
49
+ {
50
+ id: opts.id,
51
+ origin: opts.origin ?? url?.origin,
52
+ path: opts.path ?? (url?.search ? `${url.pathname}${url.search}` : url?.pathname),
53
+ method: opts.method ?? (opts.body ? 'POST' : 'GET'),
54
+ body: opts.body,
55
+ query: opts.query,
56
+ headers,
57
+ signal: opts.signal,
58
+ reset: opts.reset ?? false,
59
+ blocking: opts.blocking ?? false,
60
+ headersTimeout: opts.headersTimeout,
61
+ bodyTimeout: opts.bodyTimeout,
62
+ idempotent: opts.idempotent,
63
+ retry: opts.retry ?? 8,
64
+ proxy: opts.proxy ?? false,
65
+ cache: opts.cache ?? false,
66
+ upgrade: opts.upgrade ?? false,
67
+ follow: opts.follow ?? 8,
68
+ error: opts.error ?? true,
69
+ verify: opts.verify ?? true,
70
+ logger: opts.logger ?? null,
71
+ lookup: opts.lookup ?? null,
72
+ dns: opts.dns ?? true,
73
+ },
74
+ handler,
75
+ )
76
+ },
38
77
  )
39
78
  dispatcherCache.set(dispatcher, wrappedDispatcher)
40
79
  }
@@ -42,67 +81,23 @@ function wrapdDispatcher(dispatcher) {
42
81
  }
43
82
 
44
83
  export function dispatch(dispatcher, opts, handler) {
45
- return wrapdDispatcher(opts.dispatcher ?? undici.getGlobalDispatcher()).dispatch(opts, handler)
84
+ return wrapDispatcher(dispatcher).dispatch(opts, handler)
46
85
  }
47
86
 
48
87
  export async function request(url, opts) {
49
88
  // TODO (fix): More argument validation...
50
89
 
51
90
  if (typeof url === 'string') {
52
- url = new URL(url)
91
+ opts = { url: new URL(url), ...opts }
53
92
  } else if (url instanceof URL) {
54
- // Do nothing...
93
+ opts = { url, ...opts }
55
94
  } else if (typeof url.origin === 'string' && typeof (url.path ?? url.pathname) === 'string') {
56
- // Do nothing...
95
+ opts = { url, ...opts }
57
96
  }
58
97
 
59
98
  if (opts == null && typeof url === 'object' && url != null) {
60
99
  opts = url
61
100
  }
62
101
 
63
- if (url) {
64
- // Do nothing...
65
- } else if (typeof opts.url === 'string') {
66
- url = new URL(opts.url)
67
- } else if (url.url instanceof URL) {
68
- url = opts.url
69
- } else if (typeof opts.origin === 'string' && typeof (opts.path ?? opts.pathname) === 'string') {
70
- url = opts
71
- } else {
72
- throw new Error('missing url')
73
- }
74
-
75
- const method = opts.method ?? (opts.body ? 'POST' : 'GET')
76
- const headers = parseHeaders(opts.headers)
77
-
78
- const userAgent = opts.userAgent ?? globalThis.userAgent
79
- if (userAgent && headers?.['user-agent'] !== userAgent) {
80
- headers['user-agent'] = userAgent
81
- }
82
-
83
- return await wrapdDispatcher(opts.dispatcher ?? undici.getGlobalDispatcher()).request({
84
- id: opts.id,
85
- origin: url.origin,
86
- path: url.path ?? (url.search ? `${url.pathname}${url.search}` : url.pathname),
87
- method,
88
- body: opts.body,
89
- query: opts.query,
90
- headers,
91
- signal: opts.signal,
92
- reset: opts.reset ?? false,
93
- blocking: opts.blocking ?? false,
94
- headersTimeout: opts.headersTimeout,
95
- bodyTimeout: opts.bodyTimeout,
96
- idempotent: opts.idempotent,
97
- retry: opts.retry ?? 8,
98
- proxy: opts.proxy ?? false,
99
- cache: opts.cache ?? false,
100
- upgrade: opts.upgrade ?? false,
101
- follow: opts.follow ?? 8,
102
- error: opts.error ?? true,
103
- verify: opts.verify ?? true,
104
- logger: opts.logger ?? null,
105
- lookup: opts.lookup ?? null,
106
- dns: opts.dns ?? true,
107
- })
102
+ return await wrapDispatcher(opts.dispatcher ?? undici.getGlobalDispatcher()).request(opts)
108
103
  }
@@ -7,8 +7,14 @@ class Handler extends DecoratorHandler {
7
7
  #aborted = false
8
8
  #logger
9
9
  #pos
10
- #timing
11
- #startTime = performance.now()
10
+ #timing = {
11
+ created: performance.now(),
12
+ connect: -1,
13
+ headers: -1,
14
+ data: -1,
15
+ complete: -1,
16
+ error: -1,
17
+ }
12
18
 
13
19
  constructor(opts, { handler }) {
14
20
  super(handler)
@@ -21,13 +27,7 @@ class Handler extends DecoratorHandler {
21
27
  onConnect(abort) {
22
28
  this.#pos = 0
23
29
  this.#abort = abort
24
- this.#timing = {
25
- connect: performance.now() - this.#startTime,
26
- headers: -1,
27
- data: -1,
28
- complete: -1,
29
- error: -1,
30
- }
30
+ this.#timing.connect = performance.now() - this.#timing.created
31
31
 
32
32
  this.#logger.debug({ ureq: this.#opts }, 'upstream request started')
33
33
 
@@ -47,7 +47,7 @@ class Handler extends DecoratorHandler {
47
47
  }
48
48
 
49
49
  onHeaders(statusCode, rawHeaders, resume, statusMessage, headers = parseHeaders(rawHeaders)) {
50
- this.#timing.headers = performance.now() - this.#timing.connect - this.#startTime
50
+ this.#timing.headers = performance.now() - this.#timing.connect - this.#timing.created
51
51
 
52
52
  this.#logger.debug(
53
53
  {
@@ -62,7 +62,7 @@ class Handler extends DecoratorHandler {
62
62
 
63
63
  onData(chunk) {
64
64
  if (this.#timing.data === -1) {
65
- this.#timing.data = performance.now() - this.#timing.headers - this.#startTime
65
+ this.#timing.data = performance.now() - this.#timing.headers - this.#timing.created
66
66
  }
67
67
 
68
68
  this.#pos += chunk.length
@@ -71,7 +71,7 @@ class Handler extends DecoratorHandler {
71
71
  }
72
72
 
73
73
  onComplete(rawTrailers) {
74
- this.#timing.complete = performance.now() - this.#timing.data - this.#startTime
74
+ this.#timing.complete = performance.now() - this.#timing.data - this.#timing.created
75
75
 
76
76
  this.#logger.debug(
77
77
  { elapsedTime: this.#timing.complete, bytesRead: this.#pos, timing: this.#timing },
@@ -82,7 +82,7 @@ class Handler extends DecoratorHandler {
82
82
  }
83
83
 
84
84
  onError(err) {
85
- this.#timing.error = performance.now() - this.#timing.data - this.#startTime
85
+ this.#timing.error = performance.now() - this.#timing.data - this.#timing.created
86
86
 
87
87
  if (this.#aborted) {
88
88
  this.#logger.debug(
package/lib/utils.js CHANGED
@@ -250,6 +250,7 @@ export function bodyLength(body) {
250
250
 
251
251
  export class DecoratorHandler {
252
252
  #handler
253
+ #onConnectCalled = false
253
254
 
254
255
  constructor(handler) {
255
256
  if (typeof handler !== 'object' || handler === null) {
@@ -259,10 +260,15 @@ export class DecoratorHandler {
259
260
  }
260
261
 
261
262
  onConnect(...args) {
263
+ this.#onConnectCalled = true
262
264
  return this.#handler.onConnect?.(...args)
263
265
  }
264
266
 
265
267
  onError(...args) {
268
+ if (!this.#onConnectCalled) {
269
+ this.#onConnectCalled = true
270
+ this.#handler.onConnect?.(...args)
271
+ }
266
272
  return this.#handler.onError?.(...args)
267
273
  }
268
274
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/nxt-undici",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "main": "lib/index.js",