@earendil-works/pi-ai
Version:
Unified LLM API with automatic model discovery and provider configuration
133 lines • 4.42 kB
JavaScript
import { getProviderEnvValue } from "./provider-env.js";
const DEFAULT_PROXY_PORTS = {
ftp: 21,
gopher: 70,
http: 80,
https: 443,
ws: 80,
wss: 443,
};
function getProxyEnv(key, env) {
const lowercaseKey = key.toLowerCase();
const uppercaseKey = key.toUpperCase();
return (env?.[lowercaseKey] ||
env?.[uppercaseKey] ||
getProviderEnvValue(lowercaseKey) ||
getProviderEnvValue(uppercaseKey) ||
"");
}
function parseProxyTargetUrl(targetUrl) {
if (targetUrl instanceof URL) {
return targetUrl;
}
try {
return new URL(targetUrl);
}
catch {
return undefined;
}
}
function stripBrackets(host) {
return host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
}
function parseNoProxyEntry(entry) {
const trimmed = entry.trim().toLowerCase();
if (!trimmed)
return undefined;
if (trimmed.startsWith("[")) {
const closingBracket = trimmed.indexOf("]");
if (closingBracket !== -1) {
const host = trimmed.slice(1, closingBracket);
const rest = trimmed.slice(closingBracket + 1);
if (rest.startsWith(":")) {
const port = Number.parseInt(rest.slice(1), 10);
return { host, port: Number.isNaN(port) ? 0 : port };
}
return { host, port: 0 };
}
}
if (trimmed.includes(":") && trimmed.split(":").length > 2) {
return { host: trimmed, port: 0 };
}
const colonIndex = trimmed.lastIndexOf(":");
if (colonIndex !== -1 && colonIndex === trimmed.indexOf(":")) {
const host = trimmed.slice(0, colonIndex);
const port = Number.parseInt(trimmed.slice(colonIndex + 1), 10);
if (!Number.isNaN(port)) {
return { host, port };
}
}
return { host: trimmed, port: 0 };
}
function shouldProxyHostname(hostname, port, env) {
const noProxy = getProxyEnv("no_proxy", env).toLowerCase();
if (!noProxy) {
return true;
}
if (noProxy === "*") {
return false;
}
const normalizedTargetHost = stripBrackets(hostname.toLowerCase());
return noProxy.split(/[,\s]/).every((entry) => {
const parsed = parseNoProxyEntry(entry);
if (!parsed) {
return true;
}
if (parsed.port && parsed.port !== port) {
return true;
}
let domain = stripBrackets(parsed.host);
if (domain.startsWith("*.")) {
domain = domain.slice(2);
}
else if (domain.startsWith(".") || domain.startsWith("*")) {
domain = domain.slice(1);
}
if (!domain) {
return true;
}
if (normalizedTargetHost === domain) {
return false;
}
if (normalizedTargetHost.endsWith(`.${domain}`)) {
return false;
}
return true;
});
}
function getProxyForUrl(targetUrl, env) {
const parsedUrl = parseProxyTargetUrl(targetUrl);
if (!parsedUrl?.protocol || !parsedUrl.host) {
return "";
}
const protocol = parsedUrl.protocol.split(":", 1)[0];
const hostname = stripBrackets(parsedUrl.hostname || parsedUrl.host.replace(/:\d*$/, ""));
const port = Number.parseInt(parsedUrl.port, 10) || DEFAULT_PROXY_PORTS[protocol] || 0;
if (!shouldProxyHostname(hostname, port, env)) {
return "";
}
let proxy = getProxyEnv(`${protocol}_proxy`, env) || getProxyEnv("all_proxy", env);
if (proxy && !proxy.includes("://")) {
proxy = `${protocol}://${proxy}`;
}
return proxy;
}
export const UNSUPPORTED_PROXY_PROTOCOL_MESSAGE = "Unsupported proxy protocol. SOCKS and PAC proxy URLs are not supported; use an HTTP or HTTPS proxy URL.";
export function resolveHttpProxyUrlForTarget(targetUrl, env) {
const proxy = getProxyForUrl(targetUrl, env);
if (!proxy) {
return undefined;
}
let proxyUrl;
try {
proxyUrl = new URL(proxy);
}
catch (error) {
throw new Error(`Invalid proxy URL ${JSON.stringify(proxy)}: ${error instanceof Error ? error.message : String(error)}`);
}
if (proxyUrl.protocol !== "http:" && proxyUrl.protocol !== "https:") {
throw new Error(`${UNSUPPORTED_PROXY_PROTOCOL_MESSAGE} Got ${proxyUrl.protocol}`);
}
return proxyUrl;
}
//# sourceMappingURL=node-http-proxy.js.map