'use strict'; var parseUrl = require('url').parse; var DEFAULT_PORTS = { 'ftp:': 21, 'gopher:': 70, 'http:': 80, 'https:': 443, 'ws:': 80, 'wss:': 443, }; var stringEndsWith = String.prototype.endsWith || function(s) { return s.length <= this.length && this.indexOf(s, this.length - s.length) !== -1; }; /** * @param {string} url - The URL * @return {string} The URL of the proxy that should handle the request to the * given URL. If no proxy is set, this will be an empty string. */ function getProxyForUrl(url) { var parsedUrl = parseUrl(url); if (!parsedUrl.host || !shouldProxy(parsedUrl)) { return ''; // Don't proxy invalid URLs or URLs that match NO_PROXY. } var proto = url.split(':', 1)[0]; return getEnv(proto + '_proxy') || getEnv('all_proxy'); } /** * Determines whether a given URL should be proxied. * * @param {object} parsedUrl - The result of url.parse * @returns {boolean} Whether the given URL should be proxied. * @private */ function shouldProxy(parsedUrl) { var NO_PROXY = getEnv('no_proxy').toLowerCase(); if (!NO_PROXY) { return true; // Always proxy if NO_PROXY is not set. } if (NO_PROXY === '*') { return false; // Never proxy if wildcard is set. } var port = parseInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || 0; // Stripping ports in this way instead of using parsedUrl.hostname to make // sure that the brackets around IPv6 addresses are kept. var hostname = parsedUrl.host.replace(/:\d*$/, ''); return NO_PROXY.split(/[,\s]/).every(function(proxy) { if (!proxy) { return true; // Skip zero-length hosts. } var parsedProxy = proxy.match(/^(.+):(\d+)$/); var parsedProxyHostname = parsedProxy ? parsedProxy[1] : proxy; var parsedProxyPort = parsedProxy ? parseInt(parsedProxy[2]) : 0; if (parsedProxyPort && parsedProxyPort !== port) { return true; // Skip if ports don't match. } if (!/^[.*]/.test(parsedProxyHostname)) { // No wildcards, so stop proxying if there is an exact match. return hostname !== parsedProxyHostname; } if (parsedProxyHostname.charAt(0) === '*') { // Remove leading wildcard. parsedProxyHostname = parsedProxyHostname.slice(1); } // Stop proxying if the hostname ends with the no_proxy host. return !stringEndsWith.call(hostname, parsedProxyHostname); }); } /** * Get the value for an environment variable. * * @param {string} key - The name of the environment variable. * @return {string} The value of the environment variable. * @private */ function getEnv(key) { return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || ''; } exports.getProxyForUrl = getProxyForUrl;