UNPKG

@azure/core-rest-pipeline

Version:

Isomorphic client library for making HTTP requests in node.js and browser.

191 lines 7.12 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { HttpsProxyAgent } from "https-proxy-agent"; import { HttpProxyAgent } from "http-proxy-agent"; import { logger } from "../log.js"; const HTTPS_PROXY = "HTTPS_PROXY"; const HTTP_PROXY = "HTTP_PROXY"; const ALL_PROXY = "ALL_PROXY"; const NO_PROXY = "NO_PROXY"; /** * The programmatic identifier of the proxyPolicy. */ export const proxyPolicyName = "proxyPolicy"; /** * Stores the patterns specified in NO_PROXY environment variable. * @internal */ export const globalNoProxyList = []; let noProxyListLoaded = false; /** A cache of whether a host should bypass the proxy. */ const globalBypassedMap = new Map(); function getEnvironmentValue(name) { if (process.env[name]) { return process.env[name]; } else if (process.env[name.toLowerCase()]) { return process.env[name.toLowerCase()]; } return undefined; } function loadEnvironmentProxyValue() { if (!process) { return undefined; } const httpsProxy = getEnvironmentValue(HTTPS_PROXY); const allProxy = getEnvironmentValue(ALL_PROXY); const httpProxy = getEnvironmentValue(HTTP_PROXY); return httpsProxy || allProxy || httpProxy; } /** * Check whether the host of a given `uri` matches any pattern in the no proxy list. * If there's a match, any request sent to the same host shouldn't have the proxy settings set. * This implementation is a port of https://github.com/Azure/azure-sdk-for-net/blob/8cca811371159e527159c7eb65602477898683e2/sdk/core/Azure.Core/src/Pipeline/Internal/HttpEnvironmentProxy.cs#L210 */ function isBypassed(uri, noProxyList, bypassedMap) { if (noProxyList.length === 0) { return false; } const host = new URL(uri).hostname; if (bypassedMap === null || bypassedMap === void 0 ? void 0 : bypassedMap.has(host)) { return bypassedMap.get(host); } let isBypassedFlag = false; for (const pattern of noProxyList) { if (pattern[0] === ".") { // This should match either domain it self or any subdomain or host // .foo.com will match foo.com it self or *.foo.com if (host.endsWith(pattern)) { isBypassedFlag = true; } else { if (host.length === pattern.length - 1 && host === pattern.slice(1)) { isBypassedFlag = true; } } } else { if (host === pattern) { isBypassedFlag = true; } } } bypassedMap === null || bypassedMap === void 0 ? void 0 : bypassedMap.set(host, isBypassedFlag); return isBypassedFlag; } export function loadNoProxy() { const noProxy = getEnvironmentValue(NO_PROXY); noProxyListLoaded = true; if (noProxy) { return noProxy .split(",") .map((item) => item.trim()) .filter((item) => item.length); } return []; } /** * This method converts a proxy url into `ProxySettings` for use with ProxyPolicy. * If no argument is given, it attempts to parse a proxy URL from the environment * variables `HTTPS_PROXY` or `HTTP_PROXY`. * @param proxyUrl - The url of the proxy to use. May contain authentication information. * @deprecated - Internally this method is no longer necessary when setting proxy information. */ export function getDefaultProxySettings(proxyUrl) { if (!proxyUrl) { proxyUrl = loadEnvironmentProxyValue(); if (!proxyUrl) { return undefined; } } const parsedUrl = new URL(proxyUrl); const schema = parsedUrl.protocol ? parsedUrl.protocol + "//" : ""; return { host: schema + parsedUrl.hostname, port: Number.parseInt(parsedUrl.port || "80"), username: parsedUrl.username, password: parsedUrl.password, }; } /** * This method attempts to parse a proxy URL from the environment * variables `HTTPS_PROXY` or `HTTP_PROXY`. */ function getDefaultProxySettingsInternal() { const envProxy = loadEnvironmentProxyValue(); return envProxy ? new URL(envProxy) : undefined; } function getUrlFromProxySettings(settings) { let parsedProxyUrl; try { parsedProxyUrl = new URL(settings.host); } catch (_a) { throw new Error(`Expecting a valid host string in proxy settings, but found "${settings.host}".`); } parsedProxyUrl.port = String(settings.port); if (settings.username) { parsedProxyUrl.username = settings.username; } if (settings.password) { parsedProxyUrl.password = settings.password; } return parsedProxyUrl; } function setProxyAgentOnRequest(request, cachedAgents, proxyUrl) { // Custom Agent should take precedence so if one is present // we should skip to avoid overwriting it. if (request.agent) { return; } const url = new URL(request.url); const isInsecure = url.protocol !== "https:"; if (request.tlsSettings) { logger.warning("TLS settings are not supported in combination with custom Proxy, certificates provided to the client will be ignored."); } const headers = request.headers.toJSON(); if (isInsecure) { if (!cachedAgents.httpProxyAgent) { cachedAgents.httpProxyAgent = new HttpProxyAgent(proxyUrl, { headers }); } request.agent = cachedAgents.httpProxyAgent; } else { if (!cachedAgents.httpsProxyAgent) { cachedAgents.httpsProxyAgent = new HttpsProxyAgent(proxyUrl, { headers }); } request.agent = cachedAgents.httpsProxyAgent; } } /** * A policy that allows one to apply proxy settings to all requests. * If not passed static settings, they will be retrieved from the HTTPS_PROXY * or HTTP_PROXY environment variables. * @param proxySettings - ProxySettings to use on each request. * @param options - additional settings, for example, custom NO_PROXY patterns */ export function proxyPolicy(proxySettings, options) { if (!noProxyListLoaded) { globalNoProxyList.push(...loadNoProxy()); } const defaultProxy = proxySettings ? getUrlFromProxySettings(proxySettings) : getDefaultProxySettingsInternal(); const cachedAgents = {}; return { name: proxyPolicyName, async sendRequest(request, next) { var _a; if (!request.proxySettings && defaultProxy && !isBypassed(request.url, (_a = options === null || options === void 0 ? void 0 : options.customNoProxyList) !== null && _a !== void 0 ? _a : globalNoProxyList, (options === null || options === void 0 ? void 0 : options.customNoProxyList) ? undefined : globalBypassedMap)) { setProxyAgentOnRequest(request, cachedAgents, defaultProxy); } else if (request.proxySettings) { setProxyAgentOnRequest(request, cachedAgents, getUrlFromProxySettings(request.proxySettings)); } return next(request); }, }; } //# sourceMappingURL=proxyPolicy.js.map