insomnia/packages/insomnia-app/app/network/is-url-matched-in-no-proxy-rule.ts

49 lines
1.8 KiB
TypeScript
Raw Normal View History

import { parse as urlParse } from 'url';
function formatHostname(rawHostname) {
// canonicalize the hostname, so that 'oogle.com' won't match 'google.com'
const hostname = rawHostname.replace(/^\.*/, '.').toLowerCase();
return hostname.endsWith('.') ? hostname.slice(0, -1) : hostname;
}
function parseNoProxyZone(zone) {
zone = zone.trim().toLowerCase();
const zoneParts = zone.split(':', 2);
const zoneHost = formatHostname(zoneParts[0]);
const zonePort = zoneParts[1];
const hasPort = zone.indexOf(':') > -1;
return { hostname: zoneHost, port: zonePort, hasPort: hasPort };
}
function matchesHostname(hostname, noProxyZoneHostname) {
const wildcardNeedle = noProxyZoneHostname.startsWith('.*.') ? noProxyZoneHostname.slice(2) : noProxyZoneHostname;
const isMatchedAt = hostname.indexOf(wildcardNeedle);
return (isMatchedAt > -1 && (isMatchedAt === hostname.length - wildcardNeedle.length));
}
export function isUrlMatchedInNoProxyRule(url: string | undefined, noProxyRule: any) {
if (!url || !noProxyRule || typeof noProxyRule !== 'string') {
return false;
}
const uri = urlParse(url);
if (!uri.hostname && !uri.port && !uri.protocol) {
return false;
}
const port = uri.port || (uri.protocol === 'https:' ? '443' : '80');
const hostname = formatHostname(uri.hostname);
const noProxyList = noProxyRule.split(',');
// iterate through the noProxyList until it finds a match.
return noProxyList.map(parseNoProxyZone).some(noProxyZone => {
if (!noProxyZone.hostname && noProxyZone.hasPort) {
return port === noProxyZone.port;
}
const hostnameMatched = matchesHostname(hostname, noProxyZone.hostname);
if (noProxyZone.hasPort) {
return (port === noProxyZone.port) && hostnameMatched;
}
return hostnameMatched;
});
}