mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
feat: 统一代理配置管理,支持IPv4/IPv6协议族选择
- 新增统一代理工具 ProxyHelper,支持 SOCKS5/HTTP/HTTPS 代理 - 添加 IPv4/IPv6 协议族配置选项,默认使用 IPv4 确保兼容性 - 移除 OpenAI 路由中硬编码的 family: 4 限制 - 统一 8 个服务文件中的代理创建逻辑,避免重复维护 - 支持 OAuth 和 token 交换过程中的代理使用 - 新增配置项:PROXY_USE_IPV4(默认 true) - 向后兼容:现有配置无需手动更新 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,8 @@ CLAUDE_BETA_HEADER=claude-code-20250219,oauth-2025-04-20,interleaved-thinking-20
|
||||
# 🌐 代理配置
|
||||
DEFAULT_PROXY_TIMEOUT=60000
|
||||
MAX_PROXY_RETRIES=3
|
||||
# IP协议族配置:true=IPv4, false=IPv6, 默认IPv4(兼容性更好)
|
||||
PROXY_USE_IPV4=true
|
||||
|
||||
# 📈 使用限制
|
||||
DEFAULT_TOKEN_LIMIT=1000000
|
||||
|
||||
@@ -57,7 +57,9 @@ const config = {
|
||||
// 🌐 代理配置
|
||||
proxy: {
|
||||
timeout: parseInt(process.env.DEFAULT_PROXY_TIMEOUT) || 30000,
|
||||
maxRetries: parseInt(process.env.MAX_PROXY_RETRIES) || 3
|
||||
maxRetries: parseInt(process.env.MAX_PROXY_RETRIES) || 3,
|
||||
// IP协议族配置:true=IPv4, false=IPv6, 默认IPv4(兼容性更好)
|
||||
useIPv4: process.env.PROXY_USE_IPV4 !== 'false' // 默认 true,只有明确设置为 'false' 才使用 IPv6
|
||||
},
|
||||
|
||||
// 📈 使用限制
|
||||
|
||||
@@ -18,8 +18,7 @@ const crypto = require('crypto')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const config = require('../../config/config')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
@@ -4649,19 +4648,10 @@ router.post('/openai-accounts/exchange-code', authenticateAdmin, async (req, res
|
||||
}
|
||||
}
|
||||
|
||||
if (sessionData.proxy) {
|
||||
const { type, host, port, username, password } = sessionData.proxy
|
||||
if (type === 'socks5') {
|
||||
// SOCKS5 代理
|
||||
const auth = username && password ? `${username}:${password}@` : ''
|
||||
const socksUrl = `socks5://${auth}${host}:${port}`
|
||||
axiosConfig.httpsAgent = new SocksProxyAgent(socksUrl)
|
||||
} else if (type === 'http' || type === 'https') {
|
||||
// HTTP/HTTPS 代理
|
||||
const auth = username && password ? `${username}:${password}@` : ''
|
||||
const proxyUrl = `${type}://${auth}${host}:${port}`
|
||||
axiosConfig.httpsAgent = new HttpsProxyAgent(proxyUrl)
|
||||
}
|
||||
// 配置代理(如果有)
|
||||
const proxyAgent = ProxyHelper.createProxyAgent(sessionData.proxy)
|
||||
if (proxyAgent) {
|
||||
axiosConfig.httpsAgent = proxyAgent
|
||||
}
|
||||
|
||||
// 交换 authorization code 获取 tokens
|
||||
|
||||
@@ -8,32 +8,11 @@ const unifiedOpenAIScheduler = require('../services/unifiedOpenAIScheduler')
|
||||
const openaiAccountService = require('../services/openaiAccountService')
|
||||
const apiKeyService = require('../services/apiKeyService')
|
||||
const crypto = require('crypto')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
|
||||
// 创建代理 Agent
|
||||
// 创建代理 Agent(使用统一的代理工具)
|
||||
function createProxyAgent(proxy) {
|
||||
if (!proxy) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
if (proxy.type === 'socks5') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const socksUrl = `socks5://${auth}${proxy.host}:${proxy.port}`
|
||||
return new SocksProxyAgent(socksUrl, {
|
||||
family: 4
|
||||
})
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const proxyUrl = `${proxy.type}://${auth}${proxy.host}:${proxy.port}`
|
||||
return new HttpsProxyAgent(proxyUrl)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn('Failed to create proxy agent:', error)
|
||||
}
|
||||
|
||||
return null
|
||||
return ProxyHelper.createProxyAgent(proxy)
|
||||
}
|
||||
|
||||
// 使用统一调度器选择 OpenAI 账户
|
||||
@@ -149,11 +128,13 @@ router.post('/responses', authenticateApiKey, async (req, res) => {
|
||||
}
|
||||
|
||||
// 使用调度器选择账户
|
||||
const { accessToken, accountId, accountName, proxy, account } = await getOpenAIAuthToken(
|
||||
apiKeyData,
|
||||
sessionId,
|
||||
requestedModel
|
||||
)
|
||||
const {
|
||||
accessToken,
|
||||
accountId,
|
||||
accountName: _accountName,
|
||||
proxy,
|
||||
account
|
||||
} = await getOpenAIAuthToken(apiKeyData, sessionId, requestedModel)
|
||||
// 基于白名单构造上游所需的请求头,确保键为小写且值受控
|
||||
const incoming = req.headers || {}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
const crypto = require('crypto')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
const axios = require('axios')
|
||||
const redis = require('../models/redis')
|
||||
const logger = require('../utils/logger')
|
||||
@@ -861,29 +860,9 @@ class ClaudeAccountService {
|
||||
}
|
||||
}
|
||||
|
||||
// 🌐 创建代理agent
|
||||
// 🌐 创建代理agent(使用统一的代理工具)
|
||||
_createProxyAgent(proxyConfig) {
|
||||
if (!proxyConfig) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const proxy = JSON.parse(proxyConfig)
|
||||
|
||||
if (proxy.type === 'socks5') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const socksUrl = `socks5://${auth}${proxy.host}:${proxy.port}`
|
||||
return new SocksProxyAgent(socksUrl)
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const httpUrl = `${proxy.type}://${auth}${proxy.host}:${proxy.port}`
|
||||
return new HttpsProxyAgent(httpUrl)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn('⚠️ Invalid proxy configuration:', error)
|
||||
}
|
||||
|
||||
return null
|
||||
return ProxyHelper.createProxyAgent(proxyConfig)
|
||||
}
|
||||
|
||||
// 🔐 加密敏感数据
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
const crypto = require('crypto')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
const redis = require('../models/redis')
|
||||
const logger = require('../utils/logger')
|
||||
const config = require('../../config/config')
|
||||
@@ -480,29 +479,9 @@ class ClaudeConsoleAccountService {
|
||||
}
|
||||
}
|
||||
|
||||
// 🌐 创建代理agent
|
||||
// 🌐 创建代理agent(使用统一的代理工具)
|
||||
_createProxyAgent(proxyConfig) {
|
||||
if (!proxyConfig) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const proxy = typeof proxyConfig === 'string' ? JSON.parse(proxyConfig) : proxyConfig
|
||||
|
||||
if (proxy.type === 'socks5') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const socksUrl = `socks5://${auth}${proxy.host}:${proxy.port}`
|
||||
return new SocksProxyAgent(socksUrl)
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const httpUrl = `${proxy.type}://${auth}${proxy.host}:${proxy.port}`
|
||||
return new HttpsProxyAgent(httpUrl)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn('⚠️ Invalid proxy configuration:', error)
|
||||
}
|
||||
|
||||
return null
|
||||
return ProxyHelper.createProxyAgent(proxyConfig)
|
||||
}
|
||||
|
||||
// 🔐 加密敏感数据
|
||||
|
||||
@@ -2,8 +2,7 @@ const https = require('https')
|
||||
const zlib = require('zlib')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
const claudeAccountService = require('./claudeAccountService')
|
||||
const unifiedClaudeScheduler = require('./unifiedClaudeScheduler')
|
||||
const sessionHelper = require('../utils/sessionHelper')
|
||||
@@ -496,7 +495,7 @@ class ClaudeRelayService {
|
||||
}
|
||||
}
|
||||
|
||||
// 🌐 获取代理Agent
|
||||
// 🌐 获取代理Agent(使用统一的代理工具)
|
||||
async _getProxyAgent(accountId) {
|
||||
try {
|
||||
const accountData = await claudeAccountService.getAllAccounts()
|
||||
@@ -506,22 +505,11 @@ class ClaudeRelayService {
|
||||
return null
|
||||
}
|
||||
|
||||
const { proxy } = account
|
||||
|
||||
if (proxy.type === 'socks5') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const socksUrl = `socks5://${auth}${proxy.host}:${proxy.port}`
|
||||
return new SocksProxyAgent(socksUrl)
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const httpUrl = `${proxy.type}://${auth}${proxy.host}:${proxy.port}`
|
||||
return new HttpsProxyAgent(httpUrl)
|
||||
}
|
||||
return ProxyHelper.createProxyAgent(account.proxy)
|
||||
} catch (error) {
|
||||
logger.warn('⚠️ Failed to create proxy agent:', error)
|
||||
return null
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// 🔧 过滤客户端请求头
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const axios = require('axios')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
const logger = require('../utils/logger')
|
||||
const config = require('../../config/config')
|
||||
const apiKeyService = require('./apiKeyService')
|
||||
@@ -9,34 +8,9 @@ const apiKeyService = require('./apiKeyService')
|
||||
const GEMINI_API_BASE = 'https://cloudcode.googleapis.com/v1'
|
||||
const DEFAULT_MODEL = 'models/gemini-2.0-flash-exp'
|
||||
|
||||
// 创建代理 agent
|
||||
// 创建代理 agent(使用统一的代理工具)
|
||||
function createProxyAgent(proxyConfig) {
|
||||
if (!proxyConfig) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const proxy = typeof proxyConfig === 'string' ? JSON.parse(proxyConfig) : proxyConfig
|
||||
|
||||
if (!proxy.type || !proxy.host || !proxy.port) {
|
||||
return null
|
||||
}
|
||||
|
||||
const proxyUrl =
|
||||
proxy.username && proxy.password
|
||||
? `${proxy.type}://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`
|
||||
: `${proxy.type}://${proxy.host}:${proxy.port}`
|
||||
|
||||
if (proxy.type === 'socks5') {
|
||||
return new SocksProxyAgent(proxyUrl)
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
return new HttpsProxyAgent(proxyUrl)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error creating proxy agent:', error)
|
||||
}
|
||||
|
||||
return null
|
||||
return ProxyHelper.createProxyAgent(proxyConfig)
|
||||
}
|
||||
|
||||
// 转换 OpenAI 消息格式到 Gemini 格式
|
||||
|
||||
@@ -2,8 +2,7 @@ const redisClient = require('../models/redis')
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
const crypto = require('crypto')
|
||||
const axios = require('axios')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('../utils/proxyHelper')
|
||||
const config = require('../../config/config')
|
||||
const logger = require('../utils/logger')
|
||||
// const { maskToken } = require('../utils/tokenMask')
|
||||
@@ -133,18 +132,9 @@ async function refreshAccessToken(refreshToken, proxy = null) {
|
||||
}
|
||||
|
||||
// 配置代理(如果有)
|
||||
if (proxy && proxy.host && proxy.port) {
|
||||
if (proxy.type === 'socks5') {
|
||||
const proxyAuth =
|
||||
proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const socksProxy = `socks5://${proxyAuth}${proxy.host}:${proxy.port}`
|
||||
requestOptions.httpsAgent = new SocksProxyAgent(socksProxy)
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
const proxyAuth =
|
||||
proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
const httpProxy = `http://${proxyAuth}${proxy.host}:${proxy.port}`
|
||||
requestOptions.httpsAgent = new HttpsProxyAgent(httpProxy)
|
||||
}
|
||||
const proxyAgent = ProxyHelper.createProxyAgent(proxy)
|
||||
if (proxyAgent) {
|
||||
requestOptions.httpsAgent = proxyAgent
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
*/
|
||||
|
||||
const crypto = require('crypto')
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const ProxyHelper = require('./proxyHelper')
|
||||
const axios = require('axios')
|
||||
const logger = require('./logger')
|
||||
|
||||
@@ -125,36 +124,12 @@ function generateSetupTokenParams() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建代理agent
|
||||
* 创建代理agent(使用统一的代理工具)
|
||||
* @param {object|null} proxyConfig - 代理配置对象
|
||||
* @returns {object|null} 代理agent或null
|
||||
*/
|
||||
function createProxyAgent(proxyConfig) {
|
||||
if (!proxyConfig) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
if (proxyConfig.type === 'socks5') {
|
||||
const auth =
|
||||
proxyConfig.username && proxyConfig.password
|
||||
? `${proxyConfig.username}:${proxyConfig.password}@`
|
||||
: ''
|
||||
const socksUrl = `socks5://${auth}${proxyConfig.host}:${proxyConfig.port}`
|
||||
return new SocksProxyAgent(socksUrl)
|
||||
} else if (proxyConfig.type === 'http' || proxyConfig.type === 'https') {
|
||||
const auth =
|
||||
proxyConfig.username && proxyConfig.password
|
||||
? `${proxyConfig.username}:${proxyConfig.password}@`
|
||||
: ''
|
||||
const httpUrl = `${proxyConfig.type}://${auth}${proxyConfig.host}:${proxyConfig.port}`
|
||||
return new HttpsProxyAgent(httpUrl)
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('⚠️ Invalid proxy configuration:', error)
|
||||
}
|
||||
|
||||
return null
|
||||
return ProxyHelper.createProxyAgent(proxyConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
179
src/utils/proxyHelper.js
Normal file
179
src/utils/proxyHelper.js
Normal file
@@ -0,0 +1,179 @@
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent')
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent')
|
||||
const logger = require('./logger')
|
||||
const config = require('../../config/config')
|
||||
|
||||
/**
|
||||
* 统一的代理创建工具
|
||||
* 支持 SOCKS5 和 HTTP/HTTPS 代理,可配置 IPv4/IPv6
|
||||
*/
|
||||
class ProxyHelper {
|
||||
/**
|
||||
* 创建代理 Agent
|
||||
* @param {object|string|null} proxyConfig - 代理配置对象或 JSON 字符串
|
||||
* @param {object} options - 额外选项
|
||||
* @param {boolean|number} options.useIPv4 - 是否使用 IPv4 (true=IPv4, false=IPv6, undefined=auto)
|
||||
* @returns {Agent|null} 代理 Agent 实例或 null
|
||||
*/
|
||||
static createProxyAgent(proxyConfig, options = {}) {
|
||||
if (!proxyConfig) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
// 解析代理配置
|
||||
const proxy = typeof proxyConfig === 'string' ? JSON.parse(proxyConfig) : proxyConfig
|
||||
|
||||
// 验证必要字段
|
||||
if (!proxy.type || !proxy.host || !proxy.port) {
|
||||
logger.warn('⚠️ Invalid proxy configuration: missing required fields (type, host, port)')
|
||||
return null
|
||||
}
|
||||
|
||||
// 获取 IPv4/IPv6 配置
|
||||
const useIPv4 = ProxyHelper._getIPFamilyPreference(options.useIPv4)
|
||||
|
||||
// 构建认证信息
|
||||
const auth = proxy.username && proxy.password ? `${proxy.username}:${proxy.password}@` : ''
|
||||
|
||||
// 根据代理类型创建 Agent
|
||||
if (proxy.type === 'socks5') {
|
||||
const socksUrl = `socks5://${auth}${proxy.host}:${proxy.port}`
|
||||
const socksOptions = {}
|
||||
|
||||
// 设置 IP 协议族(如果指定)
|
||||
if (useIPv4 !== null) {
|
||||
socksOptions.family = useIPv4 ? 4 : 6
|
||||
}
|
||||
|
||||
return new SocksProxyAgent(socksUrl, socksOptions)
|
||||
} else if (proxy.type === 'http' || proxy.type === 'https') {
|
||||
const proxyUrl = `${proxy.type}://${auth}${proxy.host}:${proxy.port}`
|
||||
const httpOptions = {}
|
||||
|
||||
// HttpsProxyAgent 支持 family 参数(通过底层的 agent-base)
|
||||
if (useIPv4 !== null) {
|
||||
httpOptions.family = useIPv4 ? 4 : 6
|
||||
}
|
||||
|
||||
return new HttpsProxyAgent(proxyUrl, httpOptions)
|
||||
} else {
|
||||
logger.warn(`⚠️ Unsupported proxy type: ${proxy.type}`)
|
||||
return null
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn('⚠️ Failed to create proxy agent:', error.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 IP 协议族偏好设置
|
||||
* @param {boolean|number|string} preference - 用户偏好设置
|
||||
* @returns {boolean|null} true=IPv4, false=IPv6, null=auto
|
||||
* @private
|
||||
*/
|
||||
static _getIPFamilyPreference(preference) {
|
||||
// 如果没有指定偏好,使用配置文件或默认值
|
||||
if (preference === undefined) {
|
||||
// 从配置文件读取默认设置,默认使用 IPv4
|
||||
const defaultUseIPv4 = config.proxy?.useIPv4
|
||||
if (defaultUseIPv4 !== undefined) {
|
||||
return defaultUseIPv4
|
||||
}
|
||||
// 默认值:IPv4(兼容性更好)
|
||||
return true
|
||||
}
|
||||
|
||||
// 处理各种输入格式
|
||||
if (typeof preference === 'boolean') {
|
||||
return preference
|
||||
}
|
||||
if (typeof preference === 'number') {
|
||||
return preference === 4 ? true : preference === 6 ? false : null
|
||||
}
|
||||
if (typeof preference === 'string') {
|
||||
const lower = preference.toLowerCase()
|
||||
if (lower === 'ipv4' || lower === '4') {
|
||||
return true
|
||||
}
|
||||
if (lower === 'ipv6' || lower === '6') {
|
||||
return false
|
||||
}
|
||||
if (lower === 'auto' || lower === 'both') {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 无法识别的值,返回默认(IPv4)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证代理配置
|
||||
* @param {object|string} proxyConfig - 代理配置
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
static validateProxyConfig(proxyConfig) {
|
||||
if (!proxyConfig) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
const proxy = typeof proxyConfig === 'string' ? JSON.parse(proxyConfig) : proxyConfig
|
||||
|
||||
// 检查必要字段
|
||||
if (!proxy.type || !proxy.host || !proxy.port) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查支持的类型
|
||||
if (!['socks5', 'http', 'https'].includes(proxy.type)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查端口范围
|
||||
const port = parseInt(proxy.port)
|
||||
if (isNaN(port) || port < 1 || port > 65535) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代理配置的描述信息
|
||||
* @param {object|string} proxyConfig - 代理配置
|
||||
* @returns {string} 代理描述
|
||||
*/
|
||||
static getProxyDescription(proxyConfig) {
|
||||
if (!proxyConfig) {
|
||||
return 'No proxy'
|
||||
}
|
||||
|
||||
try {
|
||||
const proxy = typeof proxyConfig === 'string' ? JSON.parse(proxyConfig) : proxyConfig
|
||||
const hasAuth = proxy.username && proxy.password
|
||||
return `${proxy.type}://${proxy.host}:${proxy.port}${hasAuth ? ' (with auth)' : ''}`
|
||||
} catch (error) {
|
||||
return 'Invalid proxy config'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建代理 Agent(兼容旧的函数接口)
|
||||
* @param {object|string|null} proxyConfig - 代理配置
|
||||
* @param {boolean} useIPv4 - 是否使用 IPv4
|
||||
* @returns {Agent|null} 代理 Agent 实例或 null
|
||||
* @deprecated 使用 createProxyAgent 替代
|
||||
*/
|
||||
static createProxy(proxyConfig, useIPv4 = true) {
|
||||
logger.warn('⚠️ ProxyHelper.createProxy is deprecated, use createProxyAgent instead')
|
||||
return ProxyHelper.createProxyAgent(proxyConfig, { useIPv4 })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ProxyHelper
|
||||
Reference in New Issue
Block a user