AIClient-2-API/src/utils/proxy-utils.js

129 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 代理工具模块
* 支持 HTTP、HTTPS 和 SOCKS5 代理
*/
import { HttpsProxyAgent } from 'https-proxy-agent';
import logger from './logger.js';
import { HttpProxyAgent } from 'http-proxy-agent';
import { SocksProxyAgent } from 'socks-proxy-agent';
/**
* 解析代理URL并返回相应的代理配置
* @param {string} proxyUrl - 代理URL如 http://127.0.0.1:7890 或 socks5://127.0.0.1:1080
* @returns {Object|null} 代理配置对象,包含 httpAgent 和 httpsAgent
*/
export function parseProxyUrl(proxyUrl) {
if (!proxyUrl || typeof proxyUrl !== 'string') {
return null;
}
const trimmedUrl = proxyUrl.trim();
if (!trimmedUrl) {
return null;
}
try {
const url = new URL(trimmedUrl);
const protocol = url.protocol.toLowerCase();
if (protocol === 'socks5:' || protocol === 'socks4:' || protocol === 'socks:') {
// SOCKS 代理
const socksAgent = new SocksProxyAgent(trimmedUrl);
return {
httpAgent: socksAgent,
httpsAgent: socksAgent,
proxyType: 'socks'
};
} else if (protocol === 'http:' || protocol === 'https:') {
// HTTP/HTTPS 代理
return {
httpAgent: new HttpProxyAgent(trimmedUrl),
httpsAgent: new HttpsProxyAgent(trimmedUrl),
proxyType: 'http'
};
} else {
logger.warn(`[Proxy] Unsupported proxy protocol: ${protocol}`);
return null;
}
} catch (error) {
logger.error(`[Proxy] Failed to parse proxy URL: ${error.message}`);
return null;
}
}
/**
* 检查指定的提供商是否启用了代理
* @param {Object} config - 配置对象
* @param {string} providerType - 提供商类型
* @returns {boolean} 是否启用代理
*/
export function isProxyEnabledForProvider(config, providerType) {
if (!config || !config.PROXY_URL || !config.PROXY_ENABLED_PROVIDERS) {
return false;
}
const enabledProviders = config.PROXY_ENABLED_PROVIDERS;
if (!Array.isArray(enabledProviders)) {
return false;
}
return enabledProviders.includes(providerType);
}
/**
* 获取指定提供商的代理配置
* @param {Object} config - 配置对象
* @param {string} providerType - 提供商类型
* @returns {Object|null} 代理配置对象或 null
*/
export function getProxyConfigForProvider(config, providerType) {
if (!isProxyEnabledForProvider(config, providerType)) {
return null;
}
const proxyConfig = parseProxyUrl(config.PROXY_URL);
if (proxyConfig) {
logger.info(`[Proxy] Using ${proxyConfig.proxyType} proxy for ${providerType}: ${config.PROXY_URL}`);
}
return proxyConfig;
}
/**
* 为 axios 配置代理
* @param {Object} axiosConfig - axios 配置对象
* @param {Object} config - 应用配置对象
* @param {string} providerType - 提供商类型
* @returns {Object} 更新后的 axios 配置
*/
export function configureAxiosProxy(axiosConfig, config, providerType) {
const proxyConfig = getProxyConfigForProvider(config, providerType);
if (proxyConfig) {
// 使用代理 agent
axiosConfig.httpAgent = proxyConfig.httpAgent;
axiosConfig.httpsAgent = proxyConfig.httpsAgent;
// 禁用 axios 内置的代理配置,使用我们的 agent
axiosConfig.proxy = false;
}
return axiosConfig;
}
/**
* 为 google-auth-library 配置代理
* @param {Object} config - 应用配置对象
* @param {string} providerType - 提供商类型
* @returns {Object|null} transporter 配置对象或 null
*/
export function getGoogleAuthProxyConfig(config, providerType) {
const proxyConfig = getProxyConfigForProvider(config, providerType);
if (proxyConfig) {
return {
agent: proxyConfig.httpsAgent
};
}
return null;
}