File size: 4,644 Bytes
bf48b89 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | import { HttpsProxyAgent } from 'https-proxy-agent';
import { PacProxyAgent } from 'pac-proxy-agent';
import { SocksProxyAgent } from 'socks-proxy-agent';
import { ProxyAgent } from 'undici';
import { config } from '@/config';
import logger from '@/utils/logger';
import type { MultiProxyResult, ProxyState } from './multi-proxy';
import createMultiProxy from './multi-proxy';
import pacProxy from './pac-proxy';
import unifyProxy from './unify-proxy';
const proxyIsPAC = config.pacUri || config.pacScript;
interface ProxyExport {
agent: PacProxyAgent<string> | HttpsProxyAgent<string> | SocksProxyAgent | null;
dispatcher: ProxyAgent | null;
proxyUri?: string;
proxyObj: Record<string, any>;
proxyUrlHandler?: URL | null;
multiProxy?: MultiProxyResult;
getCurrentProxy: () => ProxyState | null;
markProxyFailed: (proxyUri: string) => void;
getAgentForProxy: (proxyState: ProxyState) => any;
getDispatcherForProxy: (proxyState: ProxyState) => ProxyAgent | null;
}
let proxyUri: string | undefined;
let proxyObj: Record<string, any> = {};
let proxyUrlHandler: URL | null = null;
let multiProxy: MultiProxyResult | undefined;
const createAgentForProxy = (uri: string, proxyObj: Record<string, any>): any => {
if (uri.startsWith('http')) {
return new HttpsProxyAgent(uri, {
headers: {
'proxy-authorization': proxyObj?.auth ? `Basic ${proxyObj.auth}` : undefined,
},
});
} else if (uri.startsWith('socks')) {
return new SocksProxyAgent(uri);
}
return null;
};
const createDispatcherForProxy = (uri: string, proxyObj: Record<string, any>): ProxyAgent | null => {
if (uri.startsWith('http')) {
return new ProxyAgent({
uri,
token: proxyObj?.auth ? `Basic ${proxyObj.auth}` : undefined,
requestTls: {
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0',
},
});
}
return null;
};
if (proxyIsPAC) {
const proxy = pacProxy(config.pacUri, config.pacScript, config.proxy);
proxyUri = proxy.proxyUri;
proxyObj = proxy.proxyObj;
proxyUrlHandler = proxy.proxyUrlHandler;
} else if (config.proxyUris && config.proxyUris.length > 0) {
multiProxy = createMultiProxy(config.proxyUris, config.proxy);
proxyObj = multiProxy.proxyObj;
const currentProxy = multiProxy.getNextProxy();
if (currentProxy) {
proxyUri = currentProxy.uri;
proxyUrlHandler = currentProxy.urlHandler;
}
logger.info(`Multi-proxy initialized with ${config.proxyUris.length} proxies`);
} else {
const proxy = unifyProxy(config.proxyUri, config.proxy);
proxyUri = proxy.proxyUri;
proxyObj = proxy.proxyObj;
proxyUrlHandler = proxy.proxyUrlHandler;
}
let agent: PacProxyAgent<string> | HttpsProxyAgent<string> | SocksProxyAgent | null = null;
let dispatcher: ProxyAgent | null = null;
if (proxyIsPAC && proxyUri) {
agent = new PacProxyAgent(`pac+${proxyUri}`);
} else if (proxyUri) {
agent = createAgentForProxy(proxyUri, proxyObj);
dispatcher = createDispatcherForProxy(proxyUri, proxyObj);
}
const getCurrentProxy = (): ProxyState | null => {
if (multiProxy) {
return multiProxy.getNextProxy();
}
if (proxyUri) {
return {
uri: proxyUri,
isActive: true,
failureCount: 0,
urlHandler: proxyUrlHandler,
};
}
return null;
};
const markProxyFailed = (failedProxyUri: string) => {
if (multiProxy) {
multiProxy.markProxyFailed(failedProxyUri);
const nextProxy = multiProxy.getNextProxy();
if (nextProxy) {
proxyUri = nextProxy.uri;
proxyUrlHandler = nextProxy.urlHandler || null;
agent = createAgentForProxy(nextProxy.uri, proxyObj);
dispatcher = createDispatcherForProxy(nextProxy.uri, proxyObj);
logger.info(`Switched to proxy: ${nextProxy.uri}`);
} else {
logger.warn('No available proxies remaining');
agent = null;
dispatcher = null;
proxyUri = undefined;
}
}
};
const getAgentForProxy = (proxyState: ProxyState) => createAgentForProxy(proxyState.uri, proxyObj);
const getDispatcherForProxy = (proxyState: ProxyState) => createDispatcherForProxy(proxyState.uri, proxyObj);
const proxyExport: ProxyExport = {
agent,
dispatcher,
proxyUri,
proxyObj,
proxyUrlHandler,
multiProxy,
getCurrentProxy,
markProxyFailed,
getAgentForProxy,
getDispatcherForProxy,
};
export default proxyExport;
|