* If the proxy or config afterRedirects functions are defined, call them with the options * * @param {http.ClientRequestArgs} options * @param {AxiosProxyConfig} configProxy configuration from Axios options object * @param {string} location * * @returns {http.ClientRequestArgs}
(options, configProxy, location, isRedirect, configHttpsAgent, configHttpAgent)
| 258 | * @returns {http.ClientRequestArgs} |
| 259 | */ |
| 260 | function setProxy(options, configProxy, location, isRedirect, configHttpsAgent, configHttpAgent) { |
| 261 | let proxy = configProxy; |
| 262 | const proxyEnvAgent = getProxyEnvAgent(options, configHttpAgent, configHttpsAgent); |
| 263 | if (!proxy && proxy !== false && !isNodeEnvProxyEnabled(proxyEnvAgent)) { |
| 264 | const proxyUrl = getProxyForUrl(location); |
| 265 | if (proxyUrl) { |
| 266 | if (!shouldBypassProxy(location)) { |
| 267 | proxy = new URL(proxyUrl); |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | // On redirect re-invocation, strip any stale Proxy-Authorization header carried |
| 272 | // over from the prior request (e.g. new target no longer uses a proxy, or uses |
| 273 | // a different proxy). Skip on the initial request so user-supplied headers are |
| 274 | // preserved. Header names are case-insensitive, so remove every case variant. |
| 275 | if (isRedirect && options.headers) { |
| 276 | for (const name of Object.keys(options.headers)) { |
| 277 | if (name.toLowerCase() === 'proxy-authorization') { |
| 278 | delete options.headers[name]; |
| 279 | } |
| 280 | } |
| 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 | } |
| 289 | if (proxy) { |
| 290 | // Read proxy fields without traversing the prototype chain. URL instances expose |
| 291 | // username/password/hostname/host/port/protocol via getters on URL.prototype (so |
| 292 | // direct reads are shielded), but plain object proxies — and the `auth` field |
| 293 | // (which URL does not expose) — must be guarded so a polluted Object.prototype |
| 294 | // (e.g. Object.prototype.auth = { username, password }) cannot inject |
| 295 | // attacker-controlled credentials into the Proxy-Authorization header or |
| 296 | // redirect proxying to an attacker-controlled host. |
| 297 | const isProxyURL = proxy instanceof URL; |
| 298 | const readProxyField = (key) => |
| 299 | isProxyURL || utils.hasOwnProp(proxy, key) ? proxy[key] : undefined; |
| 300 | |
| 301 | const proxyUsername = readProxyField('username'); |
| 302 | const proxyPassword = readProxyField('password'); |
| 303 | let proxyAuth = utils.hasOwnProp(proxy, 'auth') ? proxy.auth : undefined; |
| 304 | |
| 305 | // Basic proxy authorization |
| 306 | if (proxyUsername) { |
| 307 | proxyAuth = (proxyUsername || '') + ':' + (proxyPassword || ''); |
| 308 | } |
| 309 | |
| 310 | if (proxyAuth) { |
| 311 | // Support proxy auth object form. Read sub-fields via own-prop checks so a |
| 312 | // plain object inheriting from polluted Object.prototype cannot leak creds. |
| 313 | const authIsObject = typeof proxyAuth === 'object'; |
| 314 | const authUsername = |
| 315 | authIsObject && utils.hasOwnProp(proxyAuth, 'username') ? proxyAuth.username : undefined; |
| 316 | const authPassword = |
| 317 | authIsObject && utils.hasOwnProp(proxyAuth, 'password') ? proxyAuth.password : undefined; |
no test coverage detected