@zuplo/cli 6.70.16 → 6.70.22

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.
Files changed (146) hide show
  1. package/dist/cli.js +0 -6
  2. package/dist/cli.js.map +1 -1
  3. package/node_modules/@cfworker/json-schema/README.md +75 -0
  4. package/node_modules/@cfworker/json-schema/dist/commonjs/deep-compare-strict.d.ts +1 -0
  5. package/node_modules/@cfworker/json-schema/dist/commonjs/deep-compare-strict.js +42 -0
  6. package/node_modules/@cfworker/json-schema/dist/commonjs/dereference.d.ts +7 -0
  7. package/node_modules/@cfworker/json-schema/dist/commonjs/dereference.js +147 -0
  8. package/node_modules/@cfworker/json-schema/dist/commonjs/format.d.ts +1 -0
  9. package/node_modules/@cfworker/json-schema/dist/commonjs/format.js +111 -0
  10. package/node_modules/@cfworker/json-schema/dist/commonjs/index.d.ts +8 -0
  11. package/node_modules/@cfworker/json-schema/dist/commonjs/index.js +24 -0
  12. package/node_modules/@cfworker/json-schema/dist/commonjs/package.json +3 -0
  13. package/node_modules/@cfworker/json-schema/dist/commonjs/pointer.d.ts +2 -0
  14. package/node_modules/@cfworker/json-schema/dist/commonjs/pointer.js +10 -0
  15. package/node_modules/@cfworker/json-schema/dist/commonjs/types.d.ts +72 -0
  16. package/node_modules/@cfworker/json-schema/dist/commonjs/types.js +9 -0
  17. package/node_modules/@cfworker/json-schema/dist/commonjs/ucs2-length.d.ts +1 -0
  18. package/node_modules/@cfworker/json-schema/dist/commonjs/ucs2-length.js +20 -0
  19. package/node_modules/@cfworker/json-schema/dist/commonjs/validate.d.ts +3 -0
  20. package/node_modules/@cfworker/json-schema/dist/commonjs/validate.js +805 -0
  21. package/node_modules/@cfworker/json-schema/dist/commonjs/validator.d.ts +10 -0
  22. package/node_modules/@cfworker/json-schema/dist/commonjs/validator.js +27 -0
  23. package/node_modules/@cfworker/json-schema/dist/esm/deep-compare-strict.d.ts +1 -0
  24. package/node_modules/@cfworker/json-schema/dist/esm/deep-compare-strict.js +39 -0
  25. package/node_modules/@cfworker/json-schema/dist/esm/dereference.d.ts +7 -0
  26. package/node_modules/@cfworker/json-schema/dist/esm/dereference.js +143 -0
  27. package/node_modules/@cfworker/json-schema/dist/esm/format.d.ts +1 -0
  28. package/node_modules/@cfworker/json-schema/dist/esm/format.js +108 -0
  29. package/node_modules/@cfworker/json-schema/dist/esm/index.d.ts +8 -0
  30. package/node_modules/@cfworker/json-schema/dist/esm/index.js +8 -0
  31. package/node_modules/@cfworker/json-schema/dist/esm/package.json +3 -0
  32. package/node_modules/@cfworker/json-schema/dist/esm/pointer.d.ts +2 -0
  33. package/node_modules/@cfworker/json-schema/dist/esm/pointer.js +6 -0
  34. package/node_modules/@cfworker/json-schema/dist/esm/types.d.ts +72 -0
  35. package/node_modules/@cfworker/json-schema/dist/esm/types.js +6 -0
  36. package/node_modules/@cfworker/json-schema/dist/esm/ucs2-length.d.ts +1 -0
  37. package/node_modules/@cfworker/json-schema/dist/esm/ucs2-length.js +17 -0
  38. package/node_modules/@cfworker/json-schema/dist/esm/validate.d.ts +3 -0
  39. package/node_modules/@cfworker/json-schema/dist/esm/validate.js +802 -0
  40. package/node_modules/@cfworker/json-schema/dist/esm/validator.d.ts +10 -0
  41. package/node_modules/@cfworker/json-schema/dist/esm/validator.js +23 -0
  42. package/node_modules/@cfworker/json-schema/package.json +68 -0
  43. package/node_modules/@cfworker/json-schema/src/deep-compare-strict.d.ts +1 -0
  44. package/node_modules/@cfworker/json-schema/src/deep-compare-strict.ts +39 -0
  45. package/node_modules/@cfworker/json-schema/src/dereference.d.ts +12 -0
  46. package/node_modules/@cfworker/json-schema/src/dereference.ts +188 -0
  47. package/node_modules/@cfworker/json-schema/src/format.d.ts +2 -0
  48. package/node_modules/@cfworker/json-schema/src/format.ts +164 -0
  49. package/node_modules/@cfworker/json-schema/src/index.d.ts +8 -0
  50. package/node_modules/@cfworker/json-schema/src/index.ts +8 -0
  51. package/node_modules/@cfworker/json-schema/src/pointer.d.ts +2 -0
  52. package/node_modules/@cfworker/json-schema/src/pointer.ts +7 -0
  53. package/node_modules/@cfworker/json-schema/src/types.d.ts +79 -0
  54. package/node_modules/@cfworker/json-schema/src/types.ts +92 -0
  55. package/node_modules/@cfworker/json-schema/src/ucs2-length.d.ts +1 -0
  56. package/node_modules/@cfworker/json-schema/src/ucs2-length.ts +24 -0
  57. package/node_modules/@cfworker/json-schema/src/validate.d.ts +13 -0
  58. package/node_modules/@cfworker/json-schema/src/validate.ts +1168 -0
  59. package/node_modules/@cfworker/json-schema/src/validator.d.ts +14 -0
  60. package/node_modules/@cfworker/json-schema/src/validator.ts +32 -0
  61. package/node_modules/@zuplo/core/customer.cli.minified.js +1 -1
  62. package/node_modules/@zuplo/core/index.minified.js +1 -1
  63. package/node_modules/@zuplo/core/package.json +1 -1
  64. package/node_modules/@zuplo/graphql/package.json +1 -1
  65. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  66. package/node_modules/@zuplo/otel/package.json +1 -1
  67. package/node_modules/@zuplo/runtime/out/esm/{chunk-YJ3VHQXF.js → chunk-2ZQVIVZ3.js} +2 -2
  68. package/node_modules/@zuplo/runtime/out/esm/{chunk-STBDRSX7.js → chunk-UMZORQLU.js} +67 -66
  69. package/node_modules/@zuplo/runtime/out/esm/chunk-UMZORQLU.js.map +1 -0
  70. package/node_modules/@zuplo/runtime/out/esm/{chunk-KWR5BV7H.js → chunk-YGYFQCBA.js} +6 -6
  71. package/node_modules/@zuplo/runtime/out/esm/chunk-YGYFQCBA.js.map +1 -0
  72. package/node_modules/@zuplo/runtime/out/esm/{chunk-NJNTFB34.js → chunk-ZS34EO4B.js} +2 -2
  73. package/node_modules/@zuplo/runtime/out/esm/{chunk-NJNTFB34.js.map → chunk-ZS34EO4B.js.map} +1 -1
  74. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  75. package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
  76. package/node_modules/@zuplo/runtime/out/esm/internal/index.js +1 -1
  77. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +22 -1238
  78. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js.map +1 -1
  79. package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
  80. package/node_modules/@zuplo/runtime/out/types/index.d.ts +61 -12
  81. package/node_modules/@zuplo/runtime/out/types/mcp-gateway/index.d.ts +8 -17
  82. package/node_modules/@zuplo/runtime/out/types/mocks/index.d.ts +3 -12
  83. package/node_modules/@zuplo/runtime/package.json +3 -2
  84. package/node_modules/agent-base/README.md +145 -0
  85. package/node_modules/agent-base/dist/src/index.d.ts +78 -0
  86. package/node_modules/agent-base/dist/src/index.js +203 -0
  87. package/node_modules/agent-base/dist/src/index.js.map +1 -0
  88. package/node_modules/agent-base/dist/src/promisify.d.ts +4 -0
  89. package/node_modules/agent-base/dist/src/promisify.js +18 -0
  90. package/node_modules/agent-base/dist/src/promisify.js.map +1 -0
  91. package/node_modules/agent-base/package.json +64 -0
  92. package/node_modules/agent-base/src/index.ts +345 -0
  93. package/node_modules/agent-base/src/promisify.ts +33 -0
  94. package/node_modules/axios/CHANGELOG.md +71 -0
  95. package/node_modules/axios/README.md +46 -11
  96. package/node_modules/axios/dist/axios.js +81 -53
  97. package/node_modules/axios/dist/axios.js.map +1 -1
  98. package/node_modules/axios/dist/axios.min.js +2 -2
  99. package/node_modules/axios/dist/axios.min.js.map +1 -1
  100. package/node_modules/axios/dist/browser/axios.cjs +96 -64
  101. package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  102. package/node_modules/axios/dist/esm/axios.js +96 -64
  103. package/node_modules/axios/dist/esm/axios.js.map +1 -1
  104. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  105. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  106. package/node_modules/axios/dist/node/axios.cjs +206 -85
  107. package/node_modules/axios/dist/node/axios.cjs.map +1 -1
  108. package/node_modules/axios/index.d.cts +1 -1
  109. package/node_modules/axios/index.d.ts +1 -1
  110. package/node_modules/axios/lib/adapters/fetch.js +6 -2
  111. package/node_modules/axios/lib/adapters/http.js +139 -29
  112. package/node_modules/axios/lib/adapters/xhr.js +2 -1
  113. package/node_modules/axios/lib/core/AxiosHeaders.js +1 -33
  114. package/node_modules/axios/lib/env/data.js +1 -1
  115. package/node_modules/axios/lib/helpers/composeSignals.js +48 -47
  116. package/node_modules/axios/lib/helpers/formDataToJSON.js +1 -1
  117. package/node_modules/axios/lib/helpers/fromDataURI.js +18 -5
  118. package/node_modules/axios/lib/helpers/progressEventReducer.js +3 -0
  119. package/node_modules/axios/lib/helpers/sanitizeHeaderValue.js +60 -0
  120. package/node_modules/axios/lib/utils.js +8 -7
  121. package/node_modules/axios/package.json +3 -1
  122. package/node_modules/https-proxy-agent/README.md +137 -0
  123. package/node_modules/https-proxy-agent/dist/agent.d.ts +30 -0
  124. package/node_modules/https-proxy-agent/dist/agent.js +177 -0
  125. package/node_modules/https-proxy-agent/dist/agent.js.map +1 -0
  126. package/node_modules/https-proxy-agent/dist/index.d.ts +23 -0
  127. package/node_modules/https-proxy-agent/dist/index.js +14 -0
  128. package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
  129. package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +7 -0
  130. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +66 -0
  131. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
  132. package/node_modules/https-proxy-agent/package.json +56 -0
  133. package/node_modules/type-is/index.js +8 -18
  134. package/node_modules/type-is/node_modules/content-type/LICENSE +22 -0
  135. package/node_modules/type-is/node_modules/content-type/README.md +69 -0
  136. package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +26 -0
  137. package/node_modules/type-is/node_modules/content-type/dist/index.js +170 -0
  138. package/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -0
  139. package/node_modules/type-is/node_modules/content-type/package.json +52 -0
  140. package/node_modules/type-is/package.json +9 -5
  141. package/package.json +6 -6
  142. package/node_modules/@zuplo/runtime/out/esm/chunk-KWR5BV7H.js.map +0 -1
  143. package/node_modules/@zuplo/runtime/out/esm/chunk-STBDRSX7.js.map +0 -1
  144. /package/node_modules/@zuplo/runtime/out/esm/{chunk-YJ3VHQXF.js.map → chunk-2ZQVIVZ3.js.map} +0 -0
  145. /package/node_modules/@zuplo/runtime/out/esm/{chunk-STBDRSX7.js.LEGAL.txt → chunk-UMZORQLU.js.LEGAL.txt} +0 -0
  146. /package/node_modules/@zuplo/runtime/out/esm/{chunk-KWR5BV7H.js.LEGAL.txt → chunk-YGYFQCBA.js.LEGAL.txt} +0 -0
@@ -544,7 +544,7 @@ declare namespace axios {
544
544
  | LookupAddress
545
545
  >);
546
546
  withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);
547
- parseReviver?: (this: any, key: string, value: any, context?: { source: string }) => any;
547
+ parseReviver?: (this: any, key: string, value: any, context?: { source?: string }) => any;
548
548
  fetchOptions?:
549
549
  | Omit<RequestInit, 'body' | 'headers' | 'method' | 'signal'>
550
550
  | Record<string, any>;
@@ -441,7 +441,7 @@ export interface AxiosRequestConfig<D = any> {
441
441
  [address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress
442
442
  >);
443
443
  withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);
444
- parseReviver?: (this: any, key: string, value: any, context?: { source: string }) => any;
444
+ parseReviver?: (this: any, key: string, value: any, context?: { source?: string }) => any;
445
445
  fetchOptions?: Omit<RequestInit, 'body' | 'headers' | 'method' | 'signal'> | Record<string, any>;
446
446
  httpVersion?: 1 | 2;
447
447
  http2Options?: Record<string, any> & {
@@ -13,6 +13,7 @@ import resolveConfig from '../helpers/resolveConfig.js';
13
13
  import settle from '../core/settle.js';
14
14
  import estimateDataURLDecodedBytes from '../helpers/estimateDataURLDecodedBytes.js';
15
15
  import { VERSION } from '../env/data.js';
16
+ import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js';
16
17
 
17
18
  const DEFAULT_CHUNK_SIZE = 64 * 1024;
18
19
 
@@ -27,7 +28,10 @@ const test = (fn, ...args) => {
27
28
  };
28
29
 
29
30
  const factory = (env) => {
30
- const globalObject = utils.global ?? globalThis;
31
+ const globalObject =
32
+ utils.global !== undefined && utils.global !== null
33
+ ? utils.global
34
+ : globalThis;
31
35
  const { ReadableStream, TextEncoder } = globalObject;
32
36
 
33
37
  env = utils.merge.call(
@@ -284,7 +288,7 @@ const factory = (env) => {
284
288
  ...fetchOptions,
285
289
  signal: composedSignal,
286
290
  method: method.toUpperCase(),
287
- headers: headers.normalize().toJSON(),
291
+ headers: toByteStringHeaderObject(headers.normalize()),
288
292
  body: data,
289
293
  duplex: 'half',
290
294
  credentials: isCredentialsSupported ? withCredentials : undefined,
@@ -3,6 +3,7 @@ import settle from '../core/settle.js';
3
3
  import buildFullPath from '../core/buildFullPath.js';
4
4
  import buildURL from '../helpers/buildURL.js';
5
5
  import { getProxyForUrl } from 'proxy-from-env';
6
+ import HttpsProxyAgent from 'https-proxy-agent';
6
7
  import http from 'http';
7
8
  import https from 'https';
8
9
  import http2 from 'http2';
@@ -25,6 +26,7 @@ import readBlob from '../helpers/readBlob.js';
25
26
  import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';
26
27
  import callbackify from '../helpers/callbackify.js';
27
28
  import shouldBypassProxy from '../helpers/shouldBypassProxy.js';
29
+ import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js';
28
30
  import {
29
31
  progressEventReducer,
30
32
  progressEventDecorator,
@@ -67,6 +69,45 @@ function setFormDataHeaders(headers, formHeaders, policy) {
67
69
  const kAxiosSocketListener = Symbol('axios.http.socketListener');
68
70
  const kAxiosCurrentReq = Symbol('axios.http.currentReq');
69
71
 
72
+ // Tags HttpsProxyAgent instances installed by setProxy() so the redirect path
73
+ // can strip them without clobbering a user-supplied agent that happens to be
74
+ // an HttpsProxyAgent.
75
+ const kAxiosInstalledTunnel = Symbol('axios.http.installedTunnel');
76
+
77
+ // Cache of CONNECT-tunneling agents keyed by proxy config so repeat requests
78
+ // through the same proxy reuse a single agent (and its socket pool). The
79
+ // keyspace is bounded by the set of distinct proxy configs the process uses,
80
+ // so unbounded growth is not a concern in practice.
81
+ const tunnelingAgentCache = new Map();
82
+ const tunnelingAgentCacheUser = new WeakMap();
83
+
84
+ function getTunnelingAgent(agentOptions, userHttpsAgent) {
85
+ const key =
86
+ agentOptions.protocol +
87
+ '//' +
88
+ agentOptions.hostname +
89
+ ':' +
90
+ (agentOptions.port || '') +
91
+ '#' +
92
+ (agentOptions.auth || '');
93
+ const cache = userHttpsAgent
94
+ ? (tunnelingAgentCacheUser.get(userHttpsAgent) ||
95
+ tunnelingAgentCacheUser.set(userHttpsAgent, new Map()).get(userHttpsAgent))
96
+ : tunnelingAgentCache;
97
+ let agent = cache.get(key);
98
+ if (agent) return agent;
99
+ // Forward the user's TLS options (custom CA, rejectUnauthorized, client cert,
100
+ // etc.) into the tunneling agent so they apply to the origin TLS upgrade
101
+ // performed after CONNECT. Our proxy fields take precedence on conflict.
102
+ const merged = userHttpsAgent && userHttpsAgent.options
103
+ ? { ...userHttpsAgent.options, ...agentOptions }
104
+ : agentOptions;
105
+ agent = new HttpsProxyAgent(merged);
106
+ agent[kAxiosInstalledTunnel] = true;
107
+ cache.set(key, agent);
108
+ return agent;
109
+ }
110
+
70
111
  const supportedProtocols = platform.protocols.map((protocol) => {
71
112
  return protocol + ':';
72
113
  });
@@ -224,7 +265,7 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) {
224
265
  *
225
266
  * @returns {http.ClientRequestArgs}
226
267
  */
227
- function setProxy(options, configProxy, location, isRedirect) {
268
+ function setProxy(options, configProxy, location, isRedirect, configHttpsAgent) {
228
269
  let proxy = configProxy;
229
270
  if (!proxy && proxy !== false) {
230
271
  const proxyUrl = getProxyForUrl(location);
@@ -245,6 +286,13 @@ function setProxy(options, configProxy, location, isRedirect) {
245
286
  }
246
287
  }
247
288
  }
289
+ // Strip any tunneling agent we installed for the previous hop so a redirect
290
+ // that drops the proxy or crosses an HTTPS↔HTTP boundary doesn't reuse a
291
+ // stale one. Match on our Symbol marker so a user-supplied HttpsProxyAgent
292
+ // (which won't carry the marker) is left alone.
293
+ if (isRedirect && options.agent && options.agent[kAxiosInstalledTunnel]) {
294
+ options.agent = undefined;
295
+ }
248
296
  if (proxy) {
249
297
  // Read proxy fields without traversing the prototype chain. URL instances expose
250
298
  // username/password/hostname/host/port/protocol via getters on URL.prototype (so
@@ -281,40 +329,96 @@ function setProxy(options, configProxy, location, isRedirect) {
281
329
  } else if (authIsObject) {
282
330
  throw new AxiosError('Invalid proxy authorization', AxiosError.ERR_BAD_OPTION, { proxy });
283
331
  }
284
-
285
- const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64');
286
-
287
- options.headers['Proxy-Authorization'] = 'Basic ' + base64;
288
332
  }
289
333
 
290
- // Preserve a user-supplied Host header (case-insensitive) so callers can override
291
- // the value forwarded to the proxy; otherwise default to the request URL's host.
292
- let hasUserHostHeader = false;
293
- for (const name of Object.keys(options.headers)) {
294
- if (name.toLowerCase() === 'host') {
295
- hasUserHostHeader = true;
296
- break;
334
+ const targetIsHttps = isHttps.test(options.protocol);
335
+
336
+ if (targetIsHttps) {
337
+ // CONNECT-tunneling path for HTTPS targets. Preserves end-to-end TLS to
338
+ // the origin so the proxy cannot inspect the URL, headers, or body — the
339
+ // behavior already promised by THREATMODEL.md (T-R9). HttpsProxyAgent
340
+ // sends Proxy-Authorization on the CONNECT request only, never on the
341
+ // wrapped TLS request, which is why we don't stamp it onto
342
+ // options.headers here. If the user already supplied an HttpsProxyAgent,
343
+ // they own tunneling end-to-end and we leave them alone; otherwise we
344
+ // install our own tunneling agent and forward their TLS options (if any)
345
+ // so a custom httpsAgent for cert pinning / rejectUnauthorized still
346
+ // applies to the origin TLS upgrade.
347
+ if (!(configHttpsAgent instanceof HttpsProxyAgent)) {
348
+ const proxyHost = readProxyField('hostname') || readProxyField('host');
349
+ const proxyPort = readProxyField('port');
350
+ const rawProxyProtocol = readProxyField('protocol');
351
+ const normalizedProtocol = rawProxyProtocol
352
+ ? rawProxyProtocol.includes(':')
353
+ ? rawProxyProtocol
354
+ : `${rawProxyProtocol}:`
355
+ : 'http:';
356
+ // Bracket IPv6 literals for URL parsing; URL.hostname strips the
357
+ // brackets again on read so the agent receives the raw form.
358
+ const proxyHostForURL =
359
+ proxyHost && proxyHost.includes(':') && !proxyHost.startsWith('[')
360
+ ? `[${proxyHost}]`
361
+ : proxyHost;
362
+ const proxyURL = new URL(
363
+ `${normalizedProtocol}//${proxyHostForURL}${proxyPort ? ':' + proxyPort : ''}`
364
+ );
365
+ const agentOptions = {
366
+ protocol: proxyURL.protocol,
367
+ hostname: proxyURL.hostname.replace(/^\[|\]$/g, ''),
368
+ port: proxyURL.port,
369
+ auth: proxyAuth && typeof proxyAuth === 'string' ? proxyAuth : undefined,
370
+ };
371
+ if (proxyURL.protocol === 'https:') {
372
+ agentOptions.ALPNProtocols = ['http/1.1'];
373
+ }
374
+ const tunnelingAgent = getTunnelingAgent(agentOptions, configHttpsAgent);
375
+ // Set both: `options.agent` is consumed by the native https.request path
376
+ // (config.maxRedirects === 0); `options.agents.https` is consumed by
377
+ // follow-redirects, which ignores `options.agent` when `options.agents`
378
+ // is present.
379
+ options.agent = tunnelingAgent;
380
+ if (options.agents) {
381
+ options.agents.https = tunnelingAgent;
382
+ }
383
+ }
384
+ } else {
385
+ // Forward-proxy mode for plaintext HTTP targets. The request line carries
386
+ // the absolute URL and the proxy sees everything — acceptable for plain
387
+ // HTTP since the wire was already plaintext.
388
+ if (proxyAuth) {
389
+ const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64');
390
+ options.headers['Proxy-Authorization'] = 'Basic ' + base64;
391
+ }
392
+
393
+ // Preserve a user-supplied Host header (case-insensitive) so callers can override
394
+ // the value forwarded to the proxy; otherwise default to the request URL's host.
395
+ let hasUserHostHeader = false;
396
+ for (const name of Object.keys(options.headers)) {
397
+ if (name.toLowerCase() === 'host') {
398
+ hasUserHostHeader = true;
399
+ break;
400
+ }
401
+ }
402
+ if (!hasUserHostHeader) {
403
+ options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
404
+ }
405
+ const proxyHost = readProxyField('hostname') || readProxyField('host');
406
+ options.hostname = proxyHost;
407
+ // Replace 'host' since options is not a URL object
408
+ options.host = proxyHost;
409
+ options.port = readProxyField('port');
410
+ options.path = location;
411
+ const proxyProtocol = readProxyField('protocol');
412
+ if (proxyProtocol) {
413
+ options.protocol = proxyProtocol.includes(':') ? proxyProtocol : `${proxyProtocol}:`;
297
414
  }
298
- }
299
- if (!hasUserHostHeader) {
300
- options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
301
- }
302
- const proxyHost = readProxyField('hostname') || readProxyField('host');
303
- options.hostname = proxyHost;
304
- // Replace 'host' since options is not a URL object
305
- options.host = proxyHost;
306
- options.port = readProxyField('port');
307
- options.path = location;
308
- const proxyProtocol = readProxyField('protocol');
309
- if (proxyProtocol) {
310
- options.protocol = proxyProtocol.includes(':') ? proxyProtocol : `${proxyProtocol}:`;
311
415
  }
312
416
  }
313
417
 
314
418
  options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {
315
419
  // Configure proxy for redirected request, passing the original config proxy to apply
316
420
  // the exact same logic as if the redirected request was performed by axios directly.
317
- setProxy(redirectOptions, configProxy, redirectOptions.href, true);
421
+ setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent);
318
422
  };
319
423
  }
320
424
 
@@ -766,7 +870,7 @@ export default isHttpAdapterSupported &&
766
870
  const options = Object.assign(Object.create(null), {
767
871
  path,
768
872
  method: method,
769
- headers: headers.toJSON(),
873
+ headers: toByteStringHeaderObject(headers),
770
874
  agents: { http: config.httpAgent, https: config.httpsAgent },
771
875
  auth,
772
876
  protocol,
@@ -816,13 +920,19 @@ export default isHttpAdapterSupported &&
816
920
  setProxy(
817
921
  options,
818
922
  config.proxy,
819
- protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path
923
+ protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path,
924
+ false,
925
+ config.httpsAgent
820
926
  );
821
927
  }
822
928
  let transport;
823
929
  let isNativeTransport = false;
824
930
  const isHttpsRequest = isHttps.test(options.protocol);
825
- options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
931
+ // Don't clobber a CONNECT-tunneling agent installed by setProxy() for an
932
+ // HTTPS target.
933
+ if (options.agent == null) {
934
+ options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
935
+ }
826
936
 
827
937
  if (isHttp2) {
828
938
  transport = http2Transport;
@@ -8,6 +8,7 @@ import platform from '../platform/index.js';
8
8
  import AxiosHeaders from '../core/AxiosHeaders.js';
9
9
  import { progressEventReducer } from '../helpers/progressEventReducer.js';
10
10
  import resolveConfig from '../helpers/resolveConfig.js';
11
+ import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js';
11
12
 
12
13
  const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';
13
14
 
@@ -156,7 +157,7 @@ export default isXHRAdapterSupported &&
156
157
 
157
158
  // Add headers to the request
158
159
  if ('setRequestHeader' in request) {
159
- utils.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) {
160
+ utils.forEach(toByteStringHeaderObject(requestHeaders), function setRequestHeader(val, key) {
160
161
  request.setRequestHeader(key, val);
161
162
  });
162
163
  }
@@ -2,46 +2,14 @@
2
2
 
3
3
  import utils from '../utils.js';
4
4
  import parseHeaders from '../helpers/parseHeaders.js';
5
+ import { sanitizeHeaderValue } from '../helpers/sanitizeHeaderValue.js';
5
6
 
6
7
  const $internals = Symbol('internals');
7
8
 
8
- const INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g;
9
-
10
- function trimSPorHTAB(str) {
11
- let start = 0;
12
- let end = str.length;
13
-
14
- while (start < end) {
15
- const code = str.charCodeAt(start);
16
-
17
- if (code !== 0x09 && code !== 0x20) {
18
- break;
19
- }
20
-
21
- start += 1;
22
- }
23
-
24
- while (end > start) {
25
- const code = str.charCodeAt(end - 1);
26
-
27
- if (code !== 0x09 && code !== 0x20) {
28
- break;
29
- }
30
-
31
- end -= 1;
32
- }
33
-
34
- return start === 0 && end === str.length ? str : str.slice(start, end);
35
- }
36
-
37
9
  function normalizeHeader(header) {
38
10
  return header && String(header).trim().toLowerCase();
39
11
  }
40
12
 
41
- function sanitizeHeaderValue(str) {
42
- return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, ''));
43
- }
44
-
45
13
  function normalizeValue(value) {
46
14
  if (value === false || value == null) {
47
15
  return value;
@@ -1 +1 @@
1
- export const VERSION = "1.16.0";
1
+ export const VERSION = "1.16.1";
@@ -3,54 +3,55 @@ import AxiosError from '../core/AxiosError.js';
3
3
  import utils from '../utils.js';
4
4
 
5
5
  const composeSignals = (signals, timeout) => {
6
- const { length } = (signals = signals ? signals.filter(Boolean) : []);
7
-
8
- if (timeout || length) {
9
- let controller = new AbortController();
10
-
11
- let aborted;
12
-
13
- const onabort = function (reason) {
14
- if (!aborted) {
15
- aborted = true;
16
- unsubscribe();
17
- const err = reason instanceof Error ? reason : this.reason;
18
- controller.abort(
19
- err instanceof AxiosError
20
- ? err
21
- : new CanceledError(err instanceof Error ? err.message : err)
22
- );
23
- }
24
- };
25
-
26
- let timer =
27
- timeout &&
28
- setTimeout(() => {
29
- timer = null;
30
- onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT));
31
- }, timeout);
32
-
33
- const unsubscribe = () => {
34
- if (signals) {
35
- timer && clearTimeout(timer);
36
- timer = null;
37
- signals.forEach((signal) => {
38
- signal.unsubscribe
39
- ? signal.unsubscribe(onabort)
40
- : signal.removeEventListener('abort', onabort);
41
- });
42
- signals = null;
43
- }
44
- };
45
-
46
- signals.forEach((signal) => signal.addEventListener('abort', onabort));
47
-
48
- const { signal } = controller;
49
-
50
- signal.unsubscribe = () => utils.asap(unsubscribe);
51
-
52
- return signal;
6
+ signals = signals ? signals.filter(Boolean) : [];
7
+
8
+ if (!timeout && !signals.length) {
9
+ return;
53
10
  }
11
+
12
+ const controller = new AbortController();
13
+
14
+ let aborted = false;
15
+
16
+ const onabort = function (reason) {
17
+ if (!aborted) {
18
+ aborted = true;
19
+ unsubscribe();
20
+ const err = reason instanceof Error ? reason : this.reason;
21
+ controller.abort(
22
+ err instanceof AxiosError
23
+ ? err
24
+ : new CanceledError(err instanceof Error ? err.message : err)
25
+ );
26
+ }
27
+ };
28
+
29
+ let timer =
30
+ timeout &&
31
+ setTimeout(() => {
32
+ timer = null;
33
+ onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT));
34
+ }, timeout);
35
+
36
+ const unsubscribe = () => {
37
+ if (!signals) { return; }
38
+ timer && clearTimeout(timer);
39
+ timer = null;
40
+ signals.forEach((signal) => {
41
+ signal.unsubscribe
42
+ ? signal.unsubscribe(onabort)
43
+ : signal.removeEventListener('abort', onabort);
44
+ });
45
+ signals = null;
46
+ };
47
+
48
+ signals.forEach((signal) => signal.addEventListener('abort', onabort));
49
+
50
+ const { signal } = controller;
51
+
52
+ signal.unsubscribe = () => utils.asap(unsubscribe);
53
+
54
+ return signal;
54
55
  };
55
56
 
56
57
  export default composeSignals;
@@ -68,7 +68,7 @@ function formDataToJSON(formData) {
68
68
  return !isNumericKey;
69
69
  }
70
70
 
71
- if (!target[name] || !utils.isObject(target[name])) {
71
+ if (!utils.hasOwnProp(target, name) || !utils.isObject(target[name])) {
72
72
  target[name] = [];
73
73
  }
74
74
 
@@ -4,7 +4,9 @@ import AxiosError from '../core/AxiosError.js';
4
4
  import parseProtocol from './parseProtocol.js';
5
5
  import platform from '../platform/index.js';
6
6
 
7
- const DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/;
7
+ // RFC 2397: data:[<mediatype>][;base64],<data>
8
+ // mediatype = type/subtype followed by optional ;name=value parameters
9
+ const DATA_URL_PATTERN = /^([^,;]+\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\s\S]*)$/;
8
10
 
9
11
  /**
10
12
  * Parse data uri to a Buffer or Blob
@@ -33,10 +35,21 @@ export default function fromDataURI(uri, asBlob, options) {
33
35
  throw new AxiosError('Invalid URL', AxiosError.ERR_INVALID_URL);
34
36
  }
35
37
 
36
- const mime = match[1];
37
- const isBase64 = match[2];
38
- const body = match[3];
39
- const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8');
38
+ const type = match[1];
39
+ const params = match[2];
40
+ const encoding = match[3] ? 'base64' : 'utf8';
41
+ const body = match[4];
42
+
43
+ // RFC 2397 section 3: default mediatype is text/plain;charset=US-ASCII
44
+ // Bare `data:,` leaves mime undefined; Blob normalises that to "" per spec.
45
+ let mime;
46
+ if (type) {
47
+ mime = params ? type + params : type;
48
+ } else if (params) {
49
+ mime = 'text/plain' + params;
50
+ }
51
+
52
+ const buffer = Buffer.from(decodeURIComponent(body), encoding);
40
53
 
41
54
  if (asBlob) {
42
55
  if (!_Blob) {
@@ -7,6 +7,9 @@ export const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
7
7
  const _speedometer = speedometer(50, 250);
8
8
 
9
9
  return throttle((e) => {
10
+ if (!e || typeof e.loaded !== 'number') {
11
+ return;
12
+ }
10
13
  const rawLoaded = e.loaded;
11
14
  const total = e.lengthComputable ? e.total : undefined;
12
15
  const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ import utils from '../utils.js';
4
+
5
+ function trimSPorHTAB(str) {
6
+ let start = 0;
7
+ let end = str.length;
8
+
9
+ while (start < end) {
10
+ const code = str.charCodeAt(start);
11
+
12
+ if (code !== 0x09 && code !== 0x20) {
13
+ break;
14
+ }
15
+
16
+ start += 1;
17
+ }
18
+
19
+ while (end > start) {
20
+ const code = str.charCodeAt(end - 1);
21
+
22
+ if (code !== 0x09 && code !== 0x20) {
23
+ break;
24
+ }
25
+
26
+ end -= 1;
27
+ }
28
+
29
+ return start === 0 && end === str.length ? str : str.slice(start, end);
30
+ }
31
+
32
+ // The control-code ranges are intentional: header sanitization strips C0/DEL bytes.
33
+ // eslint-disable-next-line no-control-regex
34
+ const INVALID_UNICODE_HEADER_VALUE_CHARS = new RegExp('[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+', 'g');
35
+ // eslint-disable-next-line no-control-regex
36
+ const INVALID_BYTE_STRING_HEADER_VALUE_CHARS = new RegExp('[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+', 'g');
37
+
38
+ function sanitizeValue(value, invalidChars) {
39
+ if (utils.isArray(value)) {
40
+ return value.map((item) => sanitizeValue(item, invalidChars));
41
+ }
42
+
43
+ return trimSPorHTAB(String(value).replace(invalidChars, ''));
44
+ }
45
+
46
+ export const sanitizeHeaderValue = (value) =>
47
+ sanitizeValue(value, INVALID_UNICODE_HEADER_VALUE_CHARS);
48
+
49
+ export const sanitizeByteStringHeaderValue = (value) =>
50
+ sanitizeValue(value, INVALID_BYTE_STRING_HEADER_VALUE_CHARS);
51
+
52
+ export function toByteStringHeaderObject(headers) {
53
+ const byteStringHeaders = Object.create(null);
54
+
55
+ utils.forEach(headers.toJSON(), (value, header) => {
56
+ byteStringHeaders[header] = sanitizeByteStringHeaderValue(value);
57
+ });
58
+
59
+ return byteStringHeaders;
60
+ }
@@ -763,11 +763,11 @@ function isSpecCompliantForm(thing) {
763
763
  * @returns {Object} The JSON-compatible object.
764
764
  */
765
765
  const toJSONObject = (obj) => {
766
- const stack = new Array(10);
766
+ const visited = new WeakSet();
767
767
 
768
- const visit = (source, i) => {
768
+ const visit = (source) => {
769
769
  if (isObject(source)) {
770
- if (stack.indexOf(source) >= 0) {
770
+ if (visited.has(source)) {
771
771
  return;
772
772
  }
773
773
 
@@ -777,15 +777,16 @@ const toJSONObject = (obj) => {
777
777
  }
778
778
 
779
779
  if (!('toJSON' in source)) {
780
- stack[i] = source;
780
+ // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230).
781
+ visited.add(source);
781
782
  const target = isArray(source) ? [] : {};
782
783
 
783
784
  forEach(source, (value, key) => {
784
- const reducedValue = visit(value, i + 1);
785
+ const reducedValue = visit(value);
785
786
  !isUndefined(reducedValue) && (target[key] = reducedValue);
786
787
  });
787
788
 
788
- stack[i] = undefined;
789
+ visited.delete(source);
789
790
 
790
791
  return target;
791
792
  }
@@ -794,7 +795,7 @@ const toJSONObject = (obj) => {
794
795
  return source;
795
796
  };
796
797
 
797
- return visit(obj, 0);
798
+ return visit(obj);
798
799
  };
799
800
 
800
801
  /**
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axios",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
4
4
  "description": "Promise based HTTP client for the browser and node.js",
5
5
  "main": "./dist/node/axios.cjs",
6
6
  "module": "./index.js",
@@ -123,6 +123,7 @@
123
123
  "dependencies": {
124
124
  "follow-redirects": "^1.16.0",
125
125
  "form-data": "^4.0.5",
126
+ "https-proxy-agent": "^5.0.1",
126
127
  "proxy-from-env": "^2.1.0"
127
128
  },
128
129
  "devDependencies": {
@@ -140,6 +141,7 @@
140
141
  "@vitest/browser": "^4.1.5",
141
142
  "@vitest/browser-playwright": "^4.1.5",
142
143
  "abortcontroller-polyfill": "^1.7.8",
144
+ "acorn": "^8.16.0",
143
145
  "body-parser": "^2.2.2",
144
146
  "chalk": "^5.6.2",
145
147
  "cross-env": "^10.1.0",