@fontoxml/fontoxml-development-tools
Version:
Development tools for Fonto.
90 lines (78 loc) • 2.36 kB
JavaScript
import {
Dispatcher,
getGlobalDispatcher,
ProxyAgent,
setGlobalDispatcher,
} from 'undici';
// These are more of a convention than a standard. Most implementations seem to
// prioritise the lowercase variant over the uppercase one.
// See: https://about.gitlab.com/blog/2021/01/27/we-need-to-talk-no-proxy/
const HTTP_PROXY = process.env['http_proxy'] || process.env['HTTP_PROXY'];
const HTTPS_PROXY = process.env['https_proxy'] || process.env['HTTPS_PROXY'];
const NO_PROXY = process.env['no_proxy'] || process.env['NO_PROXY'];
const defaultDispatcher = getGlobalDispatcher();
class ProxyDispatcher extends Dispatcher {
constructor(proxyAgents, noProxyRules) {
super();
this.proxyAgents = proxyAgents;
this.noProxyRules = noProxyRules;
}
dispatch(options, handler) {
if (options.origin) {
const { hostname, protocol, port } = new URL(options.origin);
const proxyAgent =
this.proxyAgents[protocol] || this.proxyAgents['http:'];
const skipProxy = this.noProxyRules.some((rule) => {
if (!rule.port && rule.host === '*') {
return true;
}
// Match rule '(.)example.com' with 'example.com' and 'www.example.com', but not
// with 'other-example.com'.
if (
hostname === rule.host ||
hostname.endsWith(`.${rule.host}`)
) {
return rule.port === undefined
? true
: (port || (protocol === 'https:' ? '443' : '80')) ===
rule.port;
}
return false;
});
if (proxyAgent && !skipProxy) {
return proxyAgent.dispatch(options, handler);
}
}
return defaultDispatcher.dispatch(options, handler);
}
}
export default function configureNetworkAgent(app) {
function getProxyAgent(config) {
try {
return config ? new ProxyAgent(config) : undefined;
} catch (error) {
app.error(
undefined,
new app.logger.ErrorWithInnerError(
`Could not parse proxy configuration "${config}".`,
error
)
);
return process.exit(1);
}
}
const proxyAgents = {
'http:': getProxyAgent(HTTP_PROXY),
'https:': getProxyAgent(HTTPS_PROXY),
};
const noProxyRules = NO_PROXY
? NO_PROXY.split(',').map((rule) => {
const [host, port] = rule.trim().split(':');
return {
host: host.startsWith('.') ? host.substring(1) : host,
port,
};
})
: [];
setGlobalDispatcher(new ProxyDispatcher(proxyAgents, noProxyRules));
}