@openclaw/slack 2026.7.2-beta.2 → 2026.7.2-beta.4
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/dist/{account-configured-DzC407uv.js → account-configured-BwfXBo_F.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{account-inspect-Di7ditqZ.js → account-inspect-jn1xLaVi.js} +9 -2
- package/dist/account-reply-mode-DrUXogvO.js +14 -0
- package/dist/{accounts-BOJJiHSr.js → accounts-BSr252c_.js} +13 -25
- package/dist/accounts.runtime-CjULMLTa.js +2 -0
- package/dist/{action-runtime-Cee2ih0s.js → action-runtime-CFU52n4W.js} +11 -17
- package/dist/action-runtime.runtime-9-17zvKH.js +2 -0
- package/dist/{actions-BZiuSTIq.js → actions-D51foiwR.js} +5 -5
- package/dist/{actions.runtime-DoD0-gxw.js → actions.runtime-BMJwtf5C.js} +1 -1
- package/dist/api.js +15 -15
- package/dist/{approval-handler.runtime-CUPtIM4k.js → approval-handler.runtime-3b4-wxMl.js} +2 -2
- package/dist/{channel-DaIiGUOp.js → channel-Ds8NKvfr.js} +75 -41
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-Cfm6_6n1.js → channel-type-DXkUajFP.js} +3 -3
- package/dist/{channel.setup-C-mLz50O.js → channel.setup-DOSTEDfA.js} +8 -5
- package/dist/{config-schema-xPSnK2VK.js → config-schema-B4j4tCOI.js} +236 -30
- package/dist/{directory-config-DRkFujwG.js → directory-config-B08pm5ZT.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-D_yZhjgp.js → directory-live-DpPKzPrn.js} +2 -2
- package/dist/doctor-contract-U6oVntbM.js +173 -0
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-85UWiriS.js → group-policy-CdnQzQBI.js} +98 -125
- package/dist/{interactive-replies-BilWUdcI.js → interactive-replies-C3ffk6oN.js} +1 -1
- package/dist/interactive-replies-api.js +1 -1
- package/dist/{message-tool-api-CA9jZrCY.js → message-tool-api-ByVyIVOh.js} +3 -3
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-CalGciTs.js → monitor-CnB_WKvF.js} +3 -3
- package/dist/{outbound-adapter-BiLKcnyH.js → outbound-adapter-DuPz2HHt.js} +49 -5
- package/dist/{pipeline.runtime-DofAvTtb.js → pipeline.runtime-5rRYZuX5.js} +490 -345
- package/dist/{policy-BVs4LiSa.js → policy-C31RYSuT.js} +1 -1
- package/dist/probe-CVRuArHA.js +340 -0
- package/dist/{provider-CmeoUiIM.js → provider-htuIJGFD.js} +791 -359
- package/dist/{relay-source-DMmgtvg4.js → relay-source-Df9EaiTF.js} +6 -11
- package/dist/{replies-CJJCp6qz.js → replies-Cgr2Gli4.js} +3 -3
- package/dist/{resolve-channels-Rfts6POK.js → resolve-channels-DodP2TFx.js} +1 -1
- package/dist/{resolve-users-y6wAxR8E.js → resolve-users-M9eF8891.js} +1 -1
- package/dist/{runtime-api-BGDyOt1D.js → runtime-api-D5XYMMsf.js} +3 -2
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-CuxNQZ6v.js → scopes-CJRpHkDC.js} +1 -2
- package/dist/{secret-contract-CMohXFWS.js → secret-contract-DxmvbxBF.js} +1 -0
- package/dist/secret-contract-api.js +1 -1
- package/dist/{security-audit-CikQhBUY.js → security-audit-Cz6erklv.js} +0 -10
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-DYp8ca-l.js → send-BZ1tPv7-.js} +28 -11
- package/dist/send.runtime-a2pilFor.js +2 -0
- package/dist/setup-core-tPxMuFez.js +600 -0
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-oSd3NX9J.js → setup-surface-wV-S1dE_.js} +58 -32
- package/dist/{shared-D9yz5Otg.js → shared-BfMskaMx.js} +57 -10
- package/dist/{slash-dispatch.runtime-CSja9VuD.js → slash-dispatch.runtime-lfeIsXTX.js} +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/fs/promises.d.ts +16 -6
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/agent-base/README.md +145 -0
- package/node_modules/agent-base/dist/src/index.d.ts +78 -0
- package/node_modules/agent-base/dist/src/index.js +203 -0
- package/node_modules/agent-base/dist/src/index.js.map +1 -0
- package/node_modules/agent-base/dist/src/promisify.d.ts +4 -0
- package/node_modules/agent-base/dist/src/promisify.js +18 -0
- package/node_modules/agent-base/dist/src/promisify.js.map +1 -0
- package/node_modules/agent-base/package.json +64 -0
- package/node_modules/agent-base/src/index.ts +345 -0
- package/node_modules/agent-base/src/promisify.ts +33 -0
- package/node_modules/axios/CHANGELOG.md +197 -1
- package/node_modules/axios/README.md +424 -256
- package/node_modules/axios/dist/axios.js +589 -204
- package/node_modules/axios/dist/axios.min.js +3 -3
- package/node_modules/axios/dist/axios.min.js.map +1 -1
- package/node_modules/axios/dist/browser/axios.cjs +630 -185
- package/node_modules/axios/dist/esm/axios.js +630 -185
- package/node_modules/axios/dist/esm/axios.min.js +2 -2
- package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
- package/node_modules/axios/dist/node/axios.cjs +949 -301
- package/node_modules/axios/index.d.cts +28 -5
- package/node_modules/axios/index.d.ts +24 -3
- package/node_modules/axios/lib/adapters/adapters.js +1 -1
- package/node_modules/axios/lib/adapters/fetch.js +223 -49
- package/node_modules/axios/lib/adapters/http.js +408 -193
- package/node_modules/axios/lib/adapters/xhr.js +3 -1
- package/node_modules/axios/lib/core/Axios.js +4 -2
- package/node_modules/axios/lib/core/AxiosError.js +13 -1
- package/node_modules/axios/lib/core/AxiosHeaders.js +13 -42
- package/node_modules/axios/lib/core/buildFullPath.js +29 -1
- package/node_modules/axios/lib/core/mergeConfig.js +35 -0
- package/node_modules/axios/lib/defaults/transitional.js +2 -0
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -3
- package/node_modules/axios/lib/helpers/Http2Sessions.js +119 -0
- package/node_modules/axios/lib/helpers/buildURL.js +7 -4
- package/node_modules/axios/lib/helpers/composeSignals.js +48 -47
- package/node_modules/axios/lib/helpers/cookies.js +5 -1
- package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/node_modules/axios/lib/helpers/formDataToJSON.js +26 -4
- package/node_modules/axios/lib/helpers/formDataToStream.js +2 -2
- package/node_modules/axios/lib/helpers/fromDataURI.js +20 -5
- package/node_modules/axios/lib/helpers/progressEventReducer.js +3 -0
- package/node_modules/axios/lib/helpers/resolveConfig.js +26 -13
- package/node_modules/axios/lib/helpers/sanitizeHeaderValue.js +60 -0
- package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
- package/node_modules/axios/lib/helpers/toFormData.js +48 -12
- package/node_modules/axios/lib/helpers/validator.js +1 -1
- package/node_modules/axios/lib/utils.js +105 -19
- package/node_modules/axios/package.json +31 -13
- package/node_modules/https-proxy-agent/README.md +137 -0
- package/node_modules/https-proxy-agent/dist/agent.d.ts +30 -0
- package/node_modules/https-proxy-agent/dist/agent.js +177 -0
- package/node_modules/https-proxy-agent/dist/agent.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/index.d.ts +23 -0
- package/node_modules/https-proxy-agent/dist/index.js +14 -0
- package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +7 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +66 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
- package/node_modules/https-proxy-agent/package.json +56 -0
- package/node_modules/iconv-lite/encodings/sbcs-data.js +2 -0
- package/node_modules/iconv-lite/encodings/utf32.js +10 -3
- package/node_modules/iconv-lite/package.json +2 -2
- package/node_modules/iconv-lite/types/encodings.d.ts +2 -0
- package/node_modules/path-to-regexp/Readme.md +3 -3
- package/node_modules/path-to-regexp/dist/index.js +135 -158
- package/node_modules/path-to-regexp/dist/index.js.map +1 -1
- package/node_modules/path-to-regexp/package.json +2 -2
- package/node_modules/qs/CHANGELOG.md +11 -0
- package/node_modules/qs/dist/qs.js +17 -17
- package/node_modules/qs/lib/parse.js +19 -8
- package/node_modules/qs/lib/utils.js +47 -8
- package/node_modules/qs/package.json +6 -5
- package/node_modules/qs/test/parse.js +230 -0
- package/node_modules/qs/test/utils.js +194 -0
- package/node_modules/typebox/build/compile/validator.d.mts +1 -4
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +5 -2
- package/node_modules/typebox/build/guard/string.mjs +16 -4
- package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
- package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +29 -32
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/npm-shrinkwrap.json +54 -27
- package/openclaw.plugin.json +1331 -1424
- package/package.json +92 -14
- package/dist/accounts.runtime-KvftRRek.js +0 -2
- package/dist/action-runtime.runtime-DZfd7IFr.js +0 -2
- package/dist/client-WIPAS3Yr.js +0 -160
- package/dist/config-api-Df9a1B8C.js +0 -3
- package/dist/doctor-contract-DddfkMlF.js +0 -134
- package/dist/probe-CN0ssfLN.js +0 -48
- package/dist/send.runtime-CJLxAt26.js +0 -2
- package/dist/setup-core-CkwVLzFO.js +0 -337
- package/node_modules/axios/dist/axios.js.map +0 -1
- package/node_modules/axios/dist/browser/axios.cjs.map +0 -1
- package/node_modules/axios/dist/esm/axios.js.map +0 -1
- package/node_modules/axios/dist/node/axios.cjs.map +0 -1
|
@@ -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';
|
|
@@ -23,8 +24,10 @@ import { EventEmitter } from 'events';
|
|
|
23
24
|
import formDataToStream from '../helpers/formDataToStream.js';
|
|
24
25
|
import readBlob from '../helpers/readBlob.js';
|
|
25
26
|
import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';
|
|
27
|
+
import Http2Sessions from '../helpers/Http2Sessions.js';
|
|
26
28
|
import callbackify from '../helpers/callbackify.js';
|
|
27
29
|
import shouldBypassProxy from '../helpers/shouldBypassProxy.js';
|
|
30
|
+
import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js';
|
|
28
31
|
import {
|
|
29
32
|
progressEventReducer,
|
|
30
33
|
progressEventDecorator,
|
|
@@ -42,7 +45,15 @@ const brotliOptions = {
|
|
|
42
45
|
finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH,
|
|
43
46
|
};
|
|
44
47
|
|
|
48
|
+
const zstdOptions = {
|
|
49
|
+
flush: zlib.constants.ZSTD_e_flush,
|
|
50
|
+
finishFlush: zlib.constants.ZSTD_e_flush,
|
|
51
|
+
};
|
|
52
|
+
|
|
45
53
|
const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress);
|
|
54
|
+
const isZstdSupported = utils.isFunction(zlib.createZstdDecompress);
|
|
55
|
+
const ACCEPT_ENCODING = 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : '');
|
|
56
|
+
const ACCEPT_ENCODING_WITH_ZSTD = ACCEPT_ENCODING + (isZstdSupported ? ', zstd' : '');
|
|
46
57
|
|
|
47
58
|
const { http: httpFollow, https: httpsFollow } = followRedirects;
|
|
48
59
|
|
|
@@ -67,6 +78,100 @@ function setFormDataHeaders(headers, formHeaders, policy) {
|
|
|
67
78
|
const kAxiosSocketListener = Symbol('axios.http.socketListener');
|
|
68
79
|
const kAxiosCurrentReq = Symbol('axios.http.currentReq');
|
|
69
80
|
|
|
81
|
+
// Tags HttpsProxyAgent instances installed by setProxy() so the redirect path
|
|
82
|
+
// can strip them without clobbering a user-supplied agent that happens to be
|
|
83
|
+
// an HttpsProxyAgent.
|
|
84
|
+
const kAxiosInstalledTunnel = Symbol('axios.http.installedTunnel');
|
|
85
|
+
|
|
86
|
+
// Cache of CONNECT-tunneling agents keyed by proxy config so repeat requests
|
|
87
|
+
// through the same proxy reuse a single agent (and its socket pool). The
|
|
88
|
+
// keyspace is bounded by the set of distinct proxy configs the process uses,
|
|
89
|
+
// so unbounded growth is not a concern in practice.
|
|
90
|
+
const tunnelingAgentCache = new Map();
|
|
91
|
+
const tunnelingAgentCacheUser = new WeakMap();
|
|
92
|
+
// Minimum minor versions where Node's HTTP Agent supports native proxyEnv
|
|
93
|
+
// handling. Checking the selected agent below also covers startup modes such
|
|
94
|
+
// as NODE_OPTIONS=--use-env-proxy and --no-use-env-proxy precedence.
|
|
95
|
+
const NODE_NATIVE_ENV_PROXY_SUPPORT = {
|
|
96
|
+
22: 21,
|
|
97
|
+
24: 5,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
function isNodeNativeEnvProxySupported(nodeVersion = process.versions && process.versions.node) {
|
|
101
|
+
if (!nodeVersion) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const [major, minor] = nodeVersion.split('.').map((part) => Number(part));
|
|
106
|
+
|
|
107
|
+
if (!Number.isInteger(major) || !Number.isInteger(minor)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (major > 24) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
NODE_NATIVE_ENV_PROXY_SUPPORT[major] != null && minor >= NODE_NATIVE_ENV_PROXY_SUPPORT[major]
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function isNodeEnvProxyEnabled(agent, nodeVersion = process.versions && process.versions.node) {
|
|
121
|
+
if (!isNodeNativeEnvProxySupported(nodeVersion)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const agentOptions = agent && agent.options;
|
|
126
|
+
|
|
127
|
+
return Boolean(
|
|
128
|
+
agentOptions &&
|
|
129
|
+
utils.hasOwnProp(agentOptions, 'proxyEnv') &&
|
|
130
|
+
agentOptions.proxyEnv != null
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getProxyEnvAgent(options, configHttpAgent, configHttpsAgent) {
|
|
135
|
+
return isHttps.test(options.protocol)
|
|
136
|
+
? (configHttpsAgent || https.globalAgent)
|
|
137
|
+
: (configHttpAgent || http.globalAgent);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function getTunnelingAgent(agentOptions, userHttpsAgent) {
|
|
141
|
+
const key =
|
|
142
|
+
agentOptions.protocol +
|
|
143
|
+
'//' +
|
|
144
|
+
agentOptions.hostname +
|
|
145
|
+
':' +
|
|
146
|
+
(agentOptions.port || '') +
|
|
147
|
+
'#' +
|
|
148
|
+
(agentOptions.auth || '');
|
|
149
|
+
const cache = userHttpsAgent
|
|
150
|
+
? (tunnelingAgentCacheUser.get(userHttpsAgent) ||
|
|
151
|
+
tunnelingAgentCacheUser.set(userHttpsAgent, new Map()).get(userHttpsAgent))
|
|
152
|
+
: tunnelingAgentCache;
|
|
153
|
+
let agent = cache.get(key);
|
|
154
|
+
if (agent) return agent;
|
|
155
|
+
// Forward the user's TLS options (custom CA, rejectUnauthorized, client cert,
|
|
156
|
+
// etc.) into the tunneling agent so they apply to the origin TLS upgrade
|
|
157
|
+
// performed after CONNECT. Our proxy fields take precedence on conflict.
|
|
158
|
+
const merged = userHttpsAgent && userHttpsAgent.options
|
|
159
|
+
? { ...userHttpsAgent.options, ...agentOptions }
|
|
160
|
+
: agentOptions;
|
|
161
|
+
agent = new HttpsProxyAgent(merged);
|
|
162
|
+
if (userHttpsAgent && userHttpsAgent.options) {
|
|
163
|
+
const originTLSOptions = { ...userHttpsAgent.options };
|
|
164
|
+
const callback = agent.callback;
|
|
165
|
+
agent.callback = function axiosTunnelingAgentCallback(req, opts) {
|
|
166
|
+
// HttpsProxyAgent v5 reads callback opts for the post-CONNECT origin TLS upgrade.
|
|
167
|
+
return callback.call(this, req, { ...originTLSOptions, ...opts });
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
agent[kAxiosInstalledTunnel] = true;
|
|
171
|
+
cache.set(key, agent);
|
|
172
|
+
return agent;
|
|
173
|
+
}
|
|
174
|
+
|
|
70
175
|
const supportedProtocols = platform.protocols.map((protocol) => {
|
|
71
176
|
return protocol + ':';
|
|
72
177
|
});
|
|
@@ -93,114 +198,11 @@ const flushOnFinish = (stream, [throttled, flush]) => {
|
|
|
93
198
|
return throttled;
|
|
94
199
|
};
|
|
95
200
|
|
|
96
|
-
class Http2Sessions {
|
|
97
|
-
constructor() {
|
|
98
|
-
this.sessions = Object.create(null);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
getSession(authority, options) {
|
|
102
|
-
options = Object.assign(
|
|
103
|
-
{
|
|
104
|
-
sessionTimeout: 1000,
|
|
105
|
-
},
|
|
106
|
-
options
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
let authoritySessions = this.sessions[authority];
|
|
110
|
-
|
|
111
|
-
if (authoritySessions) {
|
|
112
|
-
let len = authoritySessions.length;
|
|
113
|
-
|
|
114
|
-
for (let i = 0; i < len; i++) {
|
|
115
|
-
const [sessionHandle, sessionOptions] = authoritySessions[i];
|
|
116
|
-
if (
|
|
117
|
-
!sessionHandle.destroyed &&
|
|
118
|
-
!sessionHandle.closed &&
|
|
119
|
-
util.isDeepStrictEqual(sessionOptions, options)
|
|
120
|
-
) {
|
|
121
|
-
return sessionHandle;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const session = http2.connect(authority, options);
|
|
127
|
-
|
|
128
|
-
let removed;
|
|
129
|
-
|
|
130
|
-
const removeSession = () => {
|
|
131
|
-
if (removed) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
removed = true;
|
|
136
|
-
|
|
137
|
-
let entries = authoritySessions,
|
|
138
|
-
len = entries.length,
|
|
139
|
-
i = len;
|
|
140
|
-
|
|
141
|
-
while (i--) {
|
|
142
|
-
if (entries[i][0] === session) {
|
|
143
|
-
if (len === 1) {
|
|
144
|
-
delete this.sessions[authority];
|
|
145
|
-
} else {
|
|
146
|
-
entries.splice(i, 1);
|
|
147
|
-
}
|
|
148
|
-
if (!session.closed) {
|
|
149
|
-
session.close();
|
|
150
|
-
}
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const originalRequestFn = session.request;
|
|
157
|
-
|
|
158
|
-
const { sessionTimeout } = options;
|
|
159
|
-
|
|
160
|
-
if (sessionTimeout != null) {
|
|
161
|
-
let timer;
|
|
162
|
-
let streamsCount = 0;
|
|
163
|
-
|
|
164
|
-
session.request = function () {
|
|
165
|
-
const stream = originalRequestFn.apply(this, arguments);
|
|
166
|
-
|
|
167
|
-
streamsCount++;
|
|
168
|
-
|
|
169
|
-
if (timer) {
|
|
170
|
-
clearTimeout(timer);
|
|
171
|
-
timer = null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
stream.once('close', () => {
|
|
175
|
-
if (!--streamsCount) {
|
|
176
|
-
timer = setTimeout(() => {
|
|
177
|
-
timer = null;
|
|
178
|
-
removeSession();
|
|
179
|
-
}, sessionTimeout);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
return stream;
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
session.once('close', removeSession);
|
|
188
|
-
|
|
189
|
-
let entry = [session, options];
|
|
190
|
-
|
|
191
|
-
authoritySessions
|
|
192
|
-
? authoritySessions.push(entry)
|
|
193
|
-
: (authoritySessions = this.sessions[authority] = [entry]);
|
|
194
|
-
|
|
195
|
-
return session;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
201
|
const http2Sessions = new Http2Sessions();
|
|
200
202
|
|
|
201
203
|
/**
|
|
202
|
-
* If the proxy or config beforeRedirects functions are defined,
|
|
203
|
-
* object.
|
|
204
|
+
* If the proxy, auth, sensitive header, or config beforeRedirects functions are defined,
|
|
205
|
+
* call them with the options object.
|
|
204
206
|
*
|
|
205
207
|
* @param {Object<string, any>} options - The options object that was passed to the request.
|
|
206
208
|
*
|
|
@@ -210,11 +212,42 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) {
|
|
|
210
212
|
if (options.beforeRedirects.proxy) {
|
|
211
213
|
options.beforeRedirects.proxy(options);
|
|
212
214
|
}
|
|
215
|
+
if (options.beforeRedirects.auth) {
|
|
216
|
+
options.beforeRedirects.auth(options);
|
|
217
|
+
}
|
|
218
|
+
if (options.beforeRedirects.sensitiveHeaders) {
|
|
219
|
+
options.beforeRedirects.sensitiveHeaders(options, requestDetails);
|
|
220
|
+
}
|
|
213
221
|
if (options.beforeRedirects.config) {
|
|
214
222
|
options.beforeRedirects.config(options, responseDetails, requestDetails);
|
|
215
223
|
}
|
|
216
224
|
}
|
|
217
225
|
|
|
226
|
+
function stripMatchingHeaders(headers, sensitiveSet) {
|
|
227
|
+
if (!headers) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
Object.keys(headers).forEach((header) => {
|
|
232
|
+
if (sensitiveSet.has(header.toLowerCase())) {
|
|
233
|
+
delete headers[header];
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function isSameOriginRedirect(redirectOptions, requestDetails) {
|
|
239
|
+
if (!requestDetails) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
return new URL(requestDetails.url).origin === new URL(redirectOptions.href).origin;
|
|
245
|
+
} catch (e) {
|
|
246
|
+
// If origin comparison fails, treat the redirect as unsafe.
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
218
251
|
/**
|
|
219
252
|
* If the proxy or config afterRedirects functions are defined, call them with the options
|
|
220
253
|
*
|
|
@@ -224,9 +257,10 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) {
|
|
|
224
257
|
*
|
|
225
258
|
* @returns {http.ClientRequestArgs}
|
|
226
259
|
*/
|
|
227
|
-
function setProxy(options, configProxy, location, isRedirect) {
|
|
260
|
+
function setProxy(options, configProxy, location, isRedirect, configHttpsAgent, configHttpAgent) {
|
|
228
261
|
let proxy = configProxy;
|
|
229
|
-
|
|
262
|
+
const proxyEnvAgent = getProxyEnvAgent(options, configHttpAgent, configHttpsAgent);
|
|
263
|
+
if (!proxy && proxy !== false && !isNodeEnvProxyEnabled(proxyEnvAgent)) {
|
|
230
264
|
const proxyUrl = getProxyForUrl(location);
|
|
231
265
|
if (proxyUrl) {
|
|
232
266
|
if (!shouldBypassProxy(location)) {
|
|
@@ -245,6 +279,13 @@ function setProxy(options, configProxy, location, isRedirect) {
|
|
|
245
279
|
}
|
|
246
280
|
}
|
|
247
281
|
}
|
|
282
|
+
// Strip any tunneling agent we installed for the previous hop so a redirect
|
|
283
|
+
// that drops the proxy or crosses an HTTPS↔HTTP boundary doesn't reuse a
|
|
284
|
+
// stale one. Match on our Symbol marker so a user-supplied HttpsProxyAgent
|
|
285
|
+
// (which won't carry the marker) is left alone.
|
|
286
|
+
if (isRedirect && options.agent && options.agent[kAxiosInstalledTunnel]) {
|
|
287
|
+
options.agent = undefined;
|
|
288
|
+
}
|
|
248
289
|
if (proxy) {
|
|
249
290
|
// Read proxy fields without traversing the prototype chain. URL instances expose
|
|
250
291
|
// username/password/hostname/host/port/protocol via getters on URL.prototype (so
|
|
@@ -281,40 +322,103 @@ function setProxy(options, configProxy, location, isRedirect) {
|
|
|
281
322
|
} else if (authIsObject) {
|
|
282
323
|
throw new AxiosError('Invalid proxy authorization', AxiosError.ERR_BAD_OPTION, { proxy });
|
|
283
324
|
}
|
|
284
|
-
|
|
285
|
-
const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64');
|
|
286
|
-
|
|
287
|
-
options.headers['Proxy-Authorization'] = 'Basic ' + base64;
|
|
288
325
|
}
|
|
289
326
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
327
|
+
const targetIsHttps = isHttps.test(options.protocol);
|
|
328
|
+
|
|
329
|
+
if (targetIsHttps) {
|
|
330
|
+
// CONNECT-tunneling path for HTTPS targets. Preserves end-to-end TLS to
|
|
331
|
+
// the origin so the proxy cannot inspect the URL, headers, or body — the
|
|
332
|
+
// behavior already promised by THREATMODEL.md (T-R9). HttpsProxyAgent
|
|
333
|
+
// sends Proxy-Authorization on the CONNECT request only, never on the
|
|
334
|
+
// wrapped TLS request, which is why we don't stamp it onto
|
|
335
|
+
// options.headers here. If the user already supplied an HttpsProxyAgent,
|
|
336
|
+
// they own tunneling end-to-end and we leave them alone; otherwise we
|
|
337
|
+
// install our own tunneling agent and forward their TLS options (if any)
|
|
338
|
+
// so a custom httpsAgent for cert pinning / rejectUnauthorized still
|
|
339
|
+
// applies to the origin TLS upgrade.
|
|
340
|
+
if (!(configHttpsAgent instanceof HttpsProxyAgent)) {
|
|
341
|
+
const proxyHost = readProxyField('hostname') || readProxyField('host');
|
|
342
|
+
const proxyPort = readProxyField('port');
|
|
343
|
+
const rawProxyProtocol = readProxyField('protocol');
|
|
344
|
+
const normalizedProtocol = rawProxyProtocol
|
|
345
|
+
? rawProxyProtocol.includes(':')
|
|
346
|
+
? rawProxyProtocol
|
|
347
|
+
: `${rawProxyProtocol}:`
|
|
348
|
+
: 'http:';
|
|
349
|
+
// Bracket IPv6 literals for URL parsing; URL.hostname strips the
|
|
350
|
+
// brackets again on read so the agent receives the raw form.
|
|
351
|
+
const proxyHostForURL =
|
|
352
|
+
proxyHost && proxyHost.includes(':') && !proxyHost.startsWith('[')
|
|
353
|
+
? `[${proxyHost}]`
|
|
354
|
+
: proxyHost;
|
|
355
|
+
const proxyURL = new URL(
|
|
356
|
+
`${normalizedProtocol}//${proxyHostForURL}${proxyPort ? ':' + proxyPort : ''}`
|
|
357
|
+
);
|
|
358
|
+
const agentOptions = {
|
|
359
|
+
protocol: proxyURL.protocol,
|
|
360
|
+
hostname: proxyURL.hostname.replace(/^\[|\]$/g, ''),
|
|
361
|
+
port: proxyURL.port,
|
|
362
|
+
auth: proxyAuth && typeof proxyAuth === 'string' ? proxyAuth : undefined,
|
|
363
|
+
};
|
|
364
|
+
if (proxyURL.protocol === 'https:') {
|
|
365
|
+
agentOptions.ALPNProtocols = ['http/1.1'];
|
|
366
|
+
}
|
|
367
|
+
const tunnelingAgent = getTunnelingAgent(agentOptions, configHttpsAgent);
|
|
368
|
+
// Set both: `options.agent` is consumed by the native https.request path
|
|
369
|
+
// (maxRedirects === 0); `options.agents.https` is consumed by
|
|
370
|
+
// follow-redirects, which ignores `options.agent` when `options.agents`
|
|
371
|
+
// is present.
|
|
372
|
+
options.agent = tunnelingAgent;
|
|
373
|
+
if (options.agents) {
|
|
374
|
+
options.agents.https = tunnelingAgent;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
} else {
|
|
378
|
+
// Forward-proxy mode for plaintext HTTP targets. The request line carries
|
|
379
|
+
// the absolute URL and the proxy sees everything — acceptable for plain
|
|
380
|
+
// HTTP since the wire was already plaintext.
|
|
381
|
+
if (proxyAuth) {
|
|
382
|
+
const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64');
|
|
383
|
+
options.headers['Proxy-Authorization'] = 'Basic ' + base64;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Preserve a user-supplied Host header (case-insensitive) so callers can override
|
|
387
|
+
// the value forwarded to the proxy; otherwise default to the request URL's host.
|
|
388
|
+
let hasUserHostHeader = false;
|
|
389
|
+
for (const name of Object.keys(options.headers)) {
|
|
390
|
+
if (name.toLowerCase() === 'host') {
|
|
391
|
+
hasUserHostHeader = true;
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (!hasUserHostHeader) {
|
|
396
|
+
options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
|
|
397
|
+
}
|
|
398
|
+
const proxyHost = readProxyField('hostname') || readProxyField('host');
|
|
399
|
+
options.hostname = proxyHost;
|
|
400
|
+
// Replace 'host' since options is not a URL object
|
|
401
|
+
options.host = proxyHost;
|
|
402
|
+
options.port = readProxyField('port');
|
|
403
|
+
options.path = location;
|
|
404
|
+
const proxyProtocol = readProxyField('protocol');
|
|
405
|
+
if (proxyProtocol) {
|
|
406
|
+
options.protocol = proxyProtocol.includes(':') ? proxyProtocol : `${proxyProtocol}:`;
|
|
297
407
|
}
|
|
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
408
|
}
|
|
312
409
|
}
|
|
313
410
|
|
|
314
411
|
options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {
|
|
315
412
|
// Configure proxy for redirected request, passing the original config proxy to apply
|
|
316
413
|
// the exact same logic as if the redirected request was performed by axios directly.
|
|
317
|
-
setProxy(
|
|
414
|
+
setProxy(
|
|
415
|
+
redirectOptions,
|
|
416
|
+
configProxy,
|
|
417
|
+
redirectOptions.href,
|
|
418
|
+
true,
|
|
419
|
+
configHttpsAgent,
|
|
420
|
+
configHttpAgent
|
|
421
|
+
);
|
|
318
422
|
};
|
|
319
423
|
}
|
|
320
424
|
|
|
@@ -413,16 +517,30 @@ const http2Transport = {
|
|
|
413
517
|
export default isHttpAdapterSupported &&
|
|
414
518
|
function httpAdapter(config) {
|
|
415
519
|
return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
|
|
416
|
-
|
|
520
|
+
// Read config pollution-safely: own properties and members inherited from
|
|
521
|
+
// a non-Object.prototype source (e.g. an Object.create(defaults) template)
|
|
522
|
+
// are honored, but values injected onto a polluted Object.prototype are
|
|
523
|
+
// ignored. All behavior-affecting reads in this adapter go through own()
|
|
524
|
+
// so the protection boundary stays consistent.
|
|
525
|
+
const own = (key) => utils.getSafeProp(config, key);
|
|
526
|
+
const transitional = own('transitional') || transitionalDefaults;
|
|
417
527
|
let data = own('data');
|
|
418
528
|
let lookup = own('lookup');
|
|
419
529
|
let family = own('family');
|
|
420
530
|
let httpVersion = own('httpVersion');
|
|
421
531
|
if (httpVersion === undefined) httpVersion = 1;
|
|
422
532
|
let http2Options = own('http2Options');
|
|
533
|
+
const httpAgent = own('httpAgent');
|
|
534
|
+
const httpsAgent = own('httpsAgent');
|
|
535
|
+
const configProxy = own('proxy');
|
|
423
536
|
const responseType = own('responseType');
|
|
424
537
|
const responseEncoding = own('responseEncoding');
|
|
425
|
-
const
|
|
538
|
+
const socketPath = own('socketPath');
|
|
539
|
+
const method = own('method').toUpperCase();
|
|
540
|
+
const maxRedirects = own('maxRedirects');
|
|
541
|
+
const maxBodyLength = own('maxBodyLength');
|
|
542
|
+
const maxContentLength = own('maxContentLength');
|
|
543
|
+
const decompress = own('decompress');
|
|
426
544
|
let isDone;
|
|
427
545
|
let rejected = false;
|
|
428
546
|
let req;
|
|
@@ -467,7 +585,7 @@ export default isHttpAdapterSupported &&
|
|
|
467
585
|
!reason || reason.type ? new CanceledError(null, config, req) : reason
|
|
468
586
|
);
|
|
469
587
|
} catch (err) {
|
|
470
|
-
|
|
588
|
+
// ignore emit errors
|
|
471
589
|
}
|
|
472
590
|
}
|
|
473
591
|
|
|
@@ -479,12 +597,13 @@ export default isHttpAdapterSupported &&
|
|
|
479
597
|
}
|
|
480
598
|
|
|
481
599
|
function createTimeoutError() {
|
|
482
|
-
|
|
483
|
-
|
|
600
|
+
const configTimeout = own('timeout');
|
|
601
|
+
let timeoutErrorMessage = configTimeout
|
|
602
|
+
? 'timeout of ' + configTimeout + 'ms exceeded'
|
|
484
603
|
: 'timeout exceeded';
|
|
485
|
-
const
|
|
486
|
-
if (
|
|
487
|
-
timeoutErrorMessage =
|
|
604
|
+
const configTimeoutErrorMessage = own('timeoutErrorMessage');
|
|
605
|
+
if (configTimeoutErrorMessage) {
|
|
606
|
+
timeoutErrorMessage = configTimeoutErrorMessage;
|
|
488
607
|
}
|
|
489
608
|
return new AxiosError(
|
|
490
609
|
timeoutErrorMessage,
|
|
@@ -540,21 +659,28 @@ export default isHttpAdapterSupported &&
|
|
|
540
659
|
});
|
|
541
660
|
|
|
542
661
|
// Parse url
|
|
543
|
-
const fullPath = buildFullPath(
|
|
544
|
-
|
|
662
|
+
const fullPath = buildFullPath(own('baseURL'), own('url'), own('allowAbsoluteUrls'), config);
|
|
663
|
+
// Unix-socket requests (own socketPath) commonly pass a path-only url
|
|
664
|
+
// like '/foo'; supply a synthetic base so new URL() can still parse it.
|
|
665
|
+
// Use the own-property value (not config.socketPath) so a polluted
|
|
666
|
+
// prototype cannot influence URL base selection.
|
|
667
|
+
const urlBase = socketPath
|
|
668
|
+
? 'http://localhost'
|
|
669
|
+
: (platform.hasBrowserEnv ? platform.origin : undefined);
|
|
670
|
+
const parsed = new URL(fullPath, urlBase);
|
|
545
671
|
const protocol = parsed.protocol || supportedProtocols[0];
|
|
546
672
|
|
|
547
673
|
if (protocol === 'data:') {
|
|
548
674
|
// Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set.
|
|
549
|
-
if (
|
|
550
|
-
// Use the exact string passed to fromDataURI (
|
|
551
|
-
const dataUrl = String(
|
|
675
|
+
if (maxContentLength > -1) {
|
|
676
|
+
// Use the exact string passed to fromDataURI (the configured url); fall back to fullPath if needed.
|
|
677
|
+
const dataUrl = String(own('url') || fullPath || '');
|
|
552
678
|
const estimated = estimateDataURLDecodedBytes(dataUrl);
|
|
553
679
|
|
|
554
|
-
if (estimated >
|
|
680
|
+
if (estimated > maxContentLength) {
|
|
555
681
|
return reject(
|
|
556
682
|
new AxiosError(
|
|
557
|
-
'maxContentLength size of ' +
|
|
683
|
+
'maxContentLength size of ' + maxContentLength + ' exceeded',
|
|
558
684
|
AxiosError.ERR_BAD_RESPONSE,
|
|
559
685
|
config
|
|
560
686
|
)
|
|
@@ -574,7 +700,7 @@ export default isHttpAdapterSupported &&
|
|
|
574
700
|
}
|
|
575
701
|
|
|
576
702
|
try {
|
|
577
|
-
convertedData = fromDataURI(
|
|
703
|
+
convertedData = fromDataURI(own('url'), responseType === 'blob', {
|
|
578
704
|
Blob: config.env && config.env.Blob,
|
|
579
705
|
});
|
|
580
706
|
} catch (err) {
|
|
@@ -674,7 +800,7 @@ export default isHttpAdapterSupported &&
|
|
|
674
800
|
// Add Content-Length header if data exists
|
|
675
801
|
headers.setContentLength(data.length, false);
|
|
676
802
|
|
|
677
|
-
if (
|
|
803
|
+
if (maxBodyLength > -1 && data.length > maxBodyLength) {
|
|
678
804
|
return reject(
|
|
679
805
|
new AxiosError(
|
|
680
806
|
'Request body larger than maxBodyLength limit',
|
|
@@ -726,12 +852,12 @@ export default isHttpAdapterSupported &&
|
|
|
726
852
|
let auth = undefined;
|
|
727
853
|
const configAuth = own('auth');
|
|
728
854
|
if (configAuth) {
|
|
729
|
-
const username = configAuth
|
|
730
|
-
const password = configAuth
|
|
855
|
+
const username = utils.getSafeProp(configAuth, 'username') || '';
|
|
856
|
+
const password = utils.getSafeProp(configAuth, 'password') || '';
|
|
731
857
|
auth = username + ':' + password;
|
|
732
858
|
}
|
|
733
859
|
|
|
734
|
-
if (!auth && parsed.username) {
|
|
860
|
+
if (!auth && (parsed.username || parsed.password)) {
|
|
735
861
|
const urlUsername = decodeURIComponentSafe(parsed.username);
|
|
736
862
|
const urlPassword = decodeURIComponentSafe(parsed.password);
|
|
737
863
|
auth = urlUsername + ':' + urlPassword;
|
|
@@ -744,20 +870,22 @@ export default isHttpAdapterSupported &&
|
|
|
744
870
|
try {
|
|
745
871
|
path = buildURL(
|
|
746
872
|
parsed.pathname + parsed.search,
|
|
747
|
-
|
|
748
|
-
|
|
873
|
+
own('params'),
|
|
874
|
+
own('paramsSerializer')
|
|
749
875
|
).replace(/^\?/, '');
|
|
750
876
|
} catch (err) {
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
877
|
+
return reject(
|
|
878
|
+
AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config, null, null, {
|
|
879
|
+
url: own('url'),
|
|
880
|
+
exists: true
|
|
881
|
+
})
|
|
882
|
+
);
|
|
756
883
|
}
|
|
757
884
|
|
|
758
885
|
headers.set(
|
|
759
886
|
'Accept-Encoding',
|
|
760
|
-
|
|
887
|
+
utils.hasOwnProp(transitional, 'advertiseZstdAcceptEncoding') &&
|
|
888
|
+
transitional.advertiseZstdAcceptEncoding === true ? ACCEPT_ENCODING_WITH_ZSTD : ACCEPT_ENCODING,
|
|
761
889
|
false
|
|
762
890
|
);
|
|
763
891
|
|
|
@@ -766,8 +894,8 @@ export default isHttpAdapterSupported &&
|
|
|
766
894
|
const options = Object.assign(Object.create(null), {
|
|
767
895
|
path,
|
|
768
896
|
method: method,
|
|
769
|
-
headers: headers
|
|
770
|
-
agents: { http:
|
|
897
|
+
headers: toByteStringHeaderObject(headers),
|
|
898
|
+
agents: { http: httpAgent, https: httpsAgent },
|
|
771
899
|
auth,
|
|
772
900
|
protocol,
|
|
773
901
|
family,
|
|
@@ -779,19 +907,20 @@ export default isHttpAdapterSupported &&
|
|
|
779
907
|
// cacheable-lookup integration hotfix
|
|
780
908
|
!utils.isUndefined(lookup) && (options.lookup = lookup);
|
|
781
909
|
|
|
782
|
-
if (
|
|
783
|
-
if (typeof
|
|
910
|
+
if (socketPath) {
|
|
911
|
+
if (typeof socketPath !== 'string') {
|
|
784
912
|
return reject(
|
|
785
913
|
new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config)
|
|
786
914
|
);
|
|
787
915
|
}
|
|
788
916
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
917
|
+
const allowedSocketPaths = own('allowedSocketPaths');
|
|
918
|
+
if (allowedSocketPaths != null) {
|
|
919
|
+
const allowed = Array.isArray(allowedSocketPaths)
|
|
920
|
+
? allowedSocketPaths
|
|
921
|
+
: [allowedSocketPaths];
|
|
793
922
|
|
|
794
|
-
const resolvedSocket = resolvePath(
|
|
923
|
+
const resolvedSocket = resolvePath(socketPath);
|
|
795
924
|
const isAllowed = allowed.some(
|
|
796
925
|
(entry) => typeof entry === 'string' && resolvePath(entry) === resolvedSocket
|
|
797
926
|
);
|
|
@@ -799,7 +928,7 @@ export default isHttpAdapterSupported &&
|
|
|
799
928
|
if (!isAllowed) {
|
|
800
929
|
return reject(
|
|
801
930
|
new AxiosError(
|
|
802
|
-
`socketPath "${
|
|
931
|
+
`socketPath "${socketPath}" is not permitted by allowedSocketPaths`,
|
|
803
932
|
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
804
933
|
config
|
|
805
934
|
)
|
|
@@ -807,7 +936,7 @@ export default isHttpAdapterSupported &&
|
|
|
807
936
|
}
|
|
808
937
|
}
|
|
809
938
|
|
|
810
|
-
options.socketPath =
|
|
939
|
+
options.socketPath = socketPath;
|
|
811
940
|
} else {
|
|
812
941
|
options.hostname = parsed.hostname.startsWith('[')
|
|
813
942
|
? parsed.hostname.slice(1, -1)
|
|
@@ -815,14 +944,26 @@ export default isHttpAdapterSupported &&
|
|
|
815
944
|
options.port = parsed.port;
|
|
816
945
|
setProxy(
|
|
817
946
|
options,
|
|
818
|
-
|
|
819
|
-
protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path
|
|
947
|
+
configProxy,
|
|
948
|
+
protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path,
|
|
949
|
+
false,
|
|
950
|
+
httpsAgent,
|
|
951
|
+
httpAgent
|
|
820
952
|
);
|
|
821
953
|
}
|
|
822
954
|
let transport;
|
|
823
955
|
let isNativeTransport = false;
|
|
956
|
+
// True only for the follow-redirects transport, which applies
|
|
957
|
+
// options.maxBodyLength itself. Every other transport (http2, native
|
|
958
|
+
// http/https, a user-supplied custom transport) needs the explicit
|
|
959
|
+
// byte-counting pipeline below to enforce maxBodyLength on streamed uploads.
|
|
960
|
+
let transportEnforcesMaxBodyLength = false;
|
|
824
961
|
const isHttpsRequest = isHttps.test(options.protocol);
|
|
825
|
-
|
|
962
|
+
// Don't clobber a CONNECT-tunneling agent installed by setProxy() for an
|
|
963
|
+
// HTTPS target.
|
|
964
|
+
if (options.agent == null) {
|
|
965
|
+
options.agent = isHttpsRequest ? httpsAgent : httpAgent;
|
|
966
|
+
}
|
|
826
967
|
|
|
827
968
|
if (isHttp2) {
|
|
828
969
|
transport = http2Transport;
|
|
@@ -830,25 +971,85 @@ export default isHttpAdapterSupported &&
|
|
|
830
971
|
const configTransport = own('transport');
|
|
831
972
|
if (configTransport) {
|
|
832
973
|
transport = configTransport;
|
|
833
|
-
} else if (
|
|
974
|
+
} else if (maxRedirects === 0) {
|
|
834
975
|
transport = isHttpsRequest ? https : http;
|
|
835
976
|
isNativeTransport = true;
|
|
836
977
|
} else {
|
|
837
|
-
|
|
838
|
-
|
|
978
|
+
transportEnforcesMaxBodyLength = true;
|
|
979
|
+
options.sensitiveHeaders = [];
|
|
980
|
+
if (maxRedirects) {
|
|
981
|
+
options.maxRedirects = maxRedirects;
|
|
839
982
|
}
|
|
840
983
|
const configBeforeRedirect = own('beforeRedirect');
|
|
841
984
|
if (configBeforeRedirect) {
|
|
842
985
|
options.beforeRedirects.config = configBeforeRedirect;
|
|
843
986
|
}
|
|
987
|
+
if (auth) {
|
|
988
|
+
// Restore HTTP Basic credentials on same-origin redirects only.
|
|
989
|
+
// follow-redirects >= 1.15.8 strips Authorization on every redirect (see #6929);
|
|
990
|
+
// cross-origin stripping is the documented mitigation for T-R2 in THREATMODEL.md
|
|
991
|
+
// and is preserved by deliberately not restoring on origin change.
|
|
992
|
+
const requestOrigin = parsed.origin;
|
|
993
|
+
const authToRestore = auth;
|
|
994
|
+
options.beforeRedirects.auth = function beforeRedirectAuth(redirectOptions) {
|
|
995
|
+
try {
|
|
996
|
+
if (new URL(redirectOptions.href).origin === requestOrigin) {
|
|
997
|
+
redirectOptions.auth = authToRestore;
|
|
998
|
+
}
|
|
999
|
+
} catch (e) {
|
|
1000
|
+
// ignore malformed URL: leaving auth stripped is fail-safe
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
const sensitiveHeaders = own('sensitiveHeaders');
|
|
1005
|
+
if (sensitiveHeaders != null) {
|
|
1006
|
+
if (!utils.isArray(sensitiveHeaders)) {
|
|
1007
|
+
return reject(
|
|
1008
|
+
new AxiosError(
|
|
1009
|
+
'sensitiveHeaders must be an array of strings',
|
|
1010
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
1011
|
+
config
|
|
1012
|
+
)
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
const sensitiveSet = new Set();
|
|
1017
|
+
for (const header of sensitiveHeaders) {
|
|
1018
|
+
if (!utils.isString(header)) {
|
|
1019
|
+
return reject(
|
|
1020
|
+
new AxiosError(
|
|
1021
|
+
'sensitiveHeaders must be an array of strings',
|
|
1022
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
1023
|
+
config
|
|
1024
|
+
)
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
sensitiveSet.add(header.toLowerCase());
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
if (sensitiveSet.size) {
|
|
1032
|
+
options.sensitiveHeaders = Array.from(sensitiveSet);
|
|
1033
|
+
options.beforeRedirects.sensitiveHeaders = function beforeRedirectSensitiveHeaders(
|
|
1034
|
+
redirectOptions,
|
|
1035
|
+
requestDetails
|
|
1036
|
+
) {
|
|
1037
|
+
if (!isSameOriginRedirect(redirectOptions, requestDetails)) {
|
|
1038
|
+
stripMatchingHeaders(redirectOptions.headers, sensitiveSet);
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
844
1043
|
transport = isHttpsRequest ? httpsFollow : httpFollow;
|
|
845
1044
|
}
|
|
846
1045
|
}
|
|
847
1046
|
|
|
848
|
-
|
|
849
|
-
|
|
1047
|
+
// Set an explicit maxBodyLength option for transports that inspect it.
|
|
1048
|
+
// When maxBodyLength is -1 (default/unlimited), use Infinity so
|
|
1049
|
+
// follow-redirects does not fall back to its own 10MB default.
|
|
1050
|
+
if (maxBodyLength > -1) {
|
|
1051
|
+
options.maxBodyLength = maxBodyLength;
|
|
850
1052
|
} else {
|
|
851
|
-
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
|
|
852
1053
|
options.maxBodyLength = Infinity;
|
|
853
1054
|
}
|
|
854
1055
|
|
|
@@ -894,7 +1095,7 @@ export default isHttpAdapterSupported &&
|
|
|
894
1095
|
const lastRequest = res.req || req;
|
|
895
1096
|
|
|
896
1097
|
// if decompress disabled we should not decompress
|
|
897
|
-
if (
|
|
1098
|
+
if (decompress !== false && res.headers['content-encoding']) {
|
|
898
1099
|
// if no content, but headers still say that it is encoded,
|
|
899
1100
|
// remove the header not confuse downstream operations
|
|
900
1101
|
if (method === 'HEAD' || res.statusCode === 204) {
|
|
@@ -927,6 +1128,13 @@ export default isHttpAdapterSupported &&
|
|
|
927
1128
|
streams.push(zlib.createBrotliDecompress(brotliOptions));
|
|
928
1129
|
delete res.headers['content-encoding'];
|
|
929
1130
|
}
|
|
1131
|
+
break;
|
|
1132
|
+
case 'zstd':
|
|
1133
|
+
if (isZstdSupported) {
|
|
1134
|
+
streams.push(zlib.createZstdDecompress(zstdOptions));
|
|
1135
|
+
delete res.headers['content-encoding'];
|
|
1136
|
+
}
|
|
1137
|
+
break;
|
|
930
1138
|
}
|
|
931
1139
|
}
|
|
932
1140
|
|
|
@@ -943,8 +1151,8 @@ export default isHttpAdapterSupported &&
|
|
|
943
1151
|
if (responseType === 'stream') {
|
|
944
1152
|
// Enforce maxContentLength on streamed responses; previously this
|
|
945
1153
|
// was applied only to buffered responses.
|
|
946
|
-
if (
|
|
947
|
-
const limit =
|
|
1154
|
+
if (maxContentLength > -1) {
|
|
1155
|
+
const limit = maxContentLength;
|
|
948
1156
|
const source = responseStream;
|
|
949
1157
|
async function* enforceMaxContentLength() {
|
|
950
1158
|
let totalResponseBytes = 0;
|
|
@@ -976,13 +1184,13 @@ export default isHttpAdapterSupported &&
|
|
|
976
1184
|
totalResponseBytes += chunk.length;
|
|
977
1185
|
|
|
978
1186
|
// make sure the content length is not over the maxContentLength if specified
|
|
979
|
-
if (
|
|
1187
|
+
if (maxContentLength > -1 && totalResponseBytes > maxContentLength) {
|
|
980
1188
|
// stream.destroy() emit aborted event before calling reject() on Node.js v16
|
|
981
1189
|
rejected = true;
|
|
982
1190
|
responseStream.destroy();
|
|
983
1191
|
abort(
|
|
984
1192
|
new AxiosError(
|
|
985
|
-
'maxContentLength size of ' +
|
|
1193
|
+
'maxContentLength size of ' + maxContentLength + ' exceeded',
|
|
986
1194
|
AxiosError.ERR_BAD_RESPONSE,
|
|
987
1195
|
config,
|
|
988
1196
|
lastRequest
|
|
@@ -1064,7 +1272,11 @@ export default isHttpAdapterSupported &&
|
|
|
1064
1272
|
|
|
1065
1273
|
req.on('socket', function handleRequestSocket(socket) {
|
|
1066
1274
|
// default interval of sending ack packet is 1 minute
|
|
1067
|
-
|
|
1275
|
+
// proxy agents (e.g. agent-base) may return a generic Duplex stream
|
|
1276
|
+
// that doesn't have setKeepAlive, so guard before calling
|
|
1277
|
+
if (typeof socket.setKeepAlive === 'function') {
|
|
1278
|
+
socket.setKeepAlive(true, 1000 * 60);
|
|
1279
|
+
}
|
|
1068
1280
|
|
|
1069
1281
|
// Install a single 'error' listener per socket (not per request) to avoid
|
|
1070
1282
|
// accumulating listeners on pooled keep-alive sockets that get reassigned
|
|
@@ -1097,9 +1309,9 @@ export default isHttpAdapterSupported &&
|
|
|
1097
1309
|
});
|
|
1098
1310
|
|
|
1099
1311
|
// Handle request timeout
|
|
1100
|
-
if (
|
|
1312
|
+
if (own('timeout')) {
|
|
1101
1313
|
// This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
|
|
1102
|
-
const timeout = parseInt(
|
|
1314
|
+
const timeout = parseInt(own('timeout'), 10);
|
|
1103
1315
|
|
|
1104
1316
|
if (Number.isNaN(timeout)) {
|
|
1105
1317
|
abort(
|
|
@@ -1157,12 +1369,13 @@ export default isHttpAdapterSupported &&
|
|
|
1157
1369
|
}
|
|
1158
1370
|
});
|
|
1159
1371
|
|
|
1160
|
-
// Enforce maxBodyLength for streamed uploads on
|
|
1161
|
-
//
|
|
1162
|
-
//
|
|
1372
|
+
// Enforce maxBodyLength for streamed uploads on every transport that
|
|
1373
|
+
// does not apply options.maxBodyLength itself (native http/https, http2,
|
|
1374
|
+
// and user-supplied custom transports). The follow-redirects transport
|
|
1375
|
+
// enforces it on the redirected HTTP/1 path.
|
|
1163
1376
|
let uploadStream = data;
|
|
1164
|
-
if (
|
|
1165
|
-
const limit =
|
|
1377
|
+
if (maxBodyLength > -1 && !transportEnforcesMaxBodyLength) {
|
|
1378
|
+
const limit = maxBodyLength;
|
|
1166
1379
|
let bytesSent = 0;
|
|
1167
1380
|
uploadStream = stream.pipeline(
|
|
1168
1381
|
[
|
|
@@ -1200,3 +1413,5 @@ export default isHttpAdapterSupported &&
|
|
|
1200
1413
|
};
|
|
1201
1414
|
|
|
1202
1415
|
export const __setProxy = setProxy;
|
|
1416
|
+
export const __isNodeEnvProxyEnabled = isNodeEnvProxyEnabled;
|
|
1417
|
+
export const __isSameOriginRedirect = isSameOriginRedirect;
|