mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2025-12-24 02:39:18 -05:00
This PR apply the HTTP(S) proxy settings defined in the Jellyseerr network tab to Axios because Axios doesn't use the proxy settings from Undici.
122 lines
3.1 KiB
TypeScript
122 lines
3.1 KiB
TypeScript
import type { ProxySettings } from '@server/lib/settings';
|
|
import logger from '@server/logger';
|
|
import axios from 'axios';
|
|
import { HttpProxyAgent } from 'http-proxy-agent';
|
|
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
import type { Dispatcher } from 'undici';
|
|
import { Agent, ProxyAgent, setGlobalDispatcher } from 'undici';
|
|
|
|
export default async function createCustomProxyAgent(
|
|
proxySettings: ProxySettings
|
|
) {
|
|
const defaultAgent = new Agent({ keepAliveTimeout: 5000 });
|
|
|
|
const skipUrl = (url: string | URL) => {
|
|
const hostname =
|
|
typeof url === 'string' ? new URL(url).hostname : url.hostname;
|
|
|
|
if (proxySettings.bypassLocalAddresses && isLocalAddress(hostname)) {
|
|
return true;
|
|
}
|
|
|
|
for (const address of proxySettings.bypassFilter.split(',')) {
|
|
const trimmedAddress = address.trim();
|
|
if (!trimmedAddress) {
|
|
continue;
|
|
}
|
|
|
|
if (trimmedAddress.startsWith('*')) {
|
|
const domain = trimmedAddress.slice(1);
|
|
if (hostname.endsWith(domain)) {
|
|
return true;
|
|
}
|
|
} else if (hostname === trimmedAddress) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
const noProxyInterceptor = (
|
|
dispatch: Dispatcher['dispatch']
|
|
): Dispatcher['dispatch'] => {
|
|
return (opts, handler) => {
|
|
return opts.origin && skipUrl(opts.origin)
|
|
? defaultAgent.dispatch(opts, handler)
|
|
: dispatch(opts, handler);
|
|
};
|
|
};
|
|
|
|
const token =
|
|
proxySettings.user && proxySettings.password
|
|
? `Basic ${Buffer.from(
|
|
`${proxySettings.user}:${proxySettings.password}`
|
|
).toString('base64')}`
|
|
: undefined;
|
|
|
|
try {
|
|
const proxyUrl =
|
|
(proxySettings.useSsl ? 'https://' : 'http://') +
|
|
proxySettings.hostname +
|
|
':' +
|
|
proxySettings.port;
|
|
|
|
const proxyAgent = new ProxyAgent({
|
|
uri: proxyUrl,
|
|
token,
|
|
keepAliveTimeout: 5000,
|
|
});
|
|
|
|
setGlobalDispatcher(proxyAgent.compose(noProxyInterceptor));
|
|
|
|
axios.defaults.httpAgent = new HttpProxyAgent(proxyUrl);
|
|
axios.defaults.httpsAgent = new HttpsProxyAgent(proxyUrl);
|
|
axios.interceptors.request.use((config) => {
|
|
if (config.url && skipUrl(config.url)) {
|
|
config.httpAgent = false;
|
|
config.httpsAgent = false;
|
|
}
|
|
return config;
|
|
});
|
|
} catch (e) {
|
|
logger.error('Failed to connect to the proxy: ' + e.message, {
|
|
label: 'Proxy',
|
|
});
|
|
setGlobalDispatcher(defaultAgent);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await axios.head('https://www.google.com');
|
|
logger.debug('HTTP(S) proxy connected successfully', { label: 'Proxy' });
|
|
} catch (e) {
|
|
logger.error(
|
|
'Failed to connect to the proxy: ' + e.message + ': ' + e.cause,
|
|
{ label: 'Proxy' }
|
|
);
|
|
setGlobalDispatcher(defaultAgent);
|
|
}
|
|
}
|
|
|
|
function isLocalAddress(hostname: string) {
|
|
if (
|
|
hostname === 'localhost' ||
|
|
hostname === '127.0.0.1' ||
|
|
hostname === '::1'
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const privateIpRanges = [
|
|
/^10\./, // 10.x.x.x
|
|
/^172\.(1[6-9]|2[0-9]|3[0-1])\./, // 172.16.x.x - 172.31.x.x
|
|
/^192\.168\./, // 192.168.x.x
|
|
];
|
|
if (privateIpRanges.some((regex) => regex.test(hostname))) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|