| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- #!/usr/bin/env tsx
- /**
- * 代理配置演示
- * 展示HTTP请求代理功能,包括会话管理和交易所专用代理
- */
- import { Config } from '../src/config/simpleEnv.js'
- import { httpClient, getWithProxy, postWithProxy } from '../src/utils/httpClient.js'
- import { installProxyFetch, restoreOriginalFetch } from '../src/utils/proxyFetch.js'
- import { logger } from '../src/utils/logger.js'
- async function proxyDemo() {
- console.log('🌐 HTTP代理配置演示')
- console.log('='.repeat(50))
- try {
- // 1. 显示代理配置状态
- console.log('\n📋 第一步: 代理配置状态检查...')
- console.log('🔧 全局代理配置:')
- console.log(` 启用状态: ${Config.proxy.enabled() ? '✅ 启用' : '❌ 禁用'}`)
- if (Config.proxy.enabled()) {
- console.log(` 服务器: ${Config.proxy.protocol()}://${Config.proxy.host()}:${Config.proxy.port()}`)
- console.log(` 用户名: ${Config.proxy.username() || '未设置'}`)
- console.log(` 会话前缀: ${Config.proxy.sessionPrefix() || '未设置'}`)
- console.log(` 会话后缀: ${Config.proxy.sessionSuffix() || '未设置'}`)
- }
- console.log('\n🎯 Aster专用代理配置:')
- console.log(` 配置状态: ${Config.proxy.aster.isConfigured() ? '✅ 已配置' : '❌ 未配置'}`)
- if (Config.proxy.aster.isConfigured()) {
- console.log(
- ` 服务器: ${Config.proxy.aster.protocol()}://${Config.proxy.aster.host()}:${Config.proxy.aster.port()}`,
- )
- console.log(` 用户名: ${Config.proxy.aster.user()}`)
- console.log(` 直接密码: ${Config.proxy.aster.pass() ? '已设置' : '未设置'}`)
- console.log(` 会话前缀: ${Config.proxy.aster.sessionPrefix() || '未设置'}`)
- console.log(` 会话后缀: ${Config.proxy.aster.sessionSuffix() || '未设置'}`)
- console.log(` 固定会话: ${Config.proxy.aster.sessionStatic() || '未设置'}`)
- // 演示密码构建
- const password = Config.proxy.buildPassword('aster')
- if (password) {
- const maskedPassword = password.substring(0, 8) + '***' + password.substring(password.length - 4)
- console.log(` 构建的密码: ${maskedPassword}`)
- }
- }
- // 2. 测试代理URL生成
- console.log('\n🔗 第二步: 代理URL生成测试...')
- const globalProxyUrl = Config.proxy.getUrl()
- const asterProxyUrl = Config.proxy.getUrl('aster')
- console.log(`全局代理URL: ${globalProxyUrl ? '已生成 ✅' : '未配置 ❌'}`)
- console.log(`Aster代理URL: ${asterProxyUrl ? '已生成 ✅' : '未配置 ❌'}`)
- if (Config.isDev()) {
- // 开发模式显示更多细节
- console.log('\n🔍 详细URL信息:')
- if (globalProxyUrl) {
- const masked = maskProxyUrl(globalProxyUrl)
- console.log(` 全局: ${masked}`)
- }
- if (asterProxyUrl) {
- const masked = maskProxyUrl(asterProxyUrl)
- console.log(` Aster: ${masked}`)
- }
- }
- // 3. HTTP客户端测试
- console.log('\n🚀 第三步: HTTP客户端代理测试...')
- if (Config.proxy.isAnyConfigured()) {
- console.log('开始HTTP请求测试 (使用代理)...')
- try {
- // 测试通用HTTP请求
- console.log('\n📡 测试通用GET请求...')
- const response1 = await httpClient.get('https://httpbin.org/ip', {
- timeout: 10000,
- retries: 1,
- })
- console.log(`✅ 通用请求成功: ${response1.status}`)
- if (response1.data?.origin) {
- const ip = response1.data.origin
- console.log(` 出口IP: ${ip}`)
- }
- // 测试Aster专用代理请求
- if (Config.proxy.aster.isConfigured()) {
- console.log('\n🎯 测试Aster专用代理请求...')
- const response2 = await httpClient.get('https://httpbin.org/ip', {
- exchange: 'aster',
- timeout: 10000,
- retries: 1,
- })
- console.log(`✅ Aster专用请求成功: ${response2.status}`)
- if (response2.data?.origin) {
- const ip = response2.data.origin
- console.log(` Aster出口IP: ${ip}`)
- }
- }
- } catch (error: any) {
- console.error(`❌ HTTP请求失败: ${error.message}`)
- logger.error('代理HTTP请求失败', { error: error.message })
- }
- } else {
- console.log('⚠️ 未配置代理,跳过HTTP测试')
- }
- // 4. 便捷方法测试
- console.log('\n⚡ 第四步: 便捷方法测试...')
- if (Config.proxy.isAnyConfigured()) {
- try {
- console.log('测试便捷GET方法...')
- const data = await getWithProxy('https://httpbin.org/json', {
- timeout: 10000,
- retries: 1,
- })
- console.log(`✅ 便捷GET成功`)
- console.log('测试便捷POST方法...')
- const postData = await postWithProxy(
- 'https://httpbin.org/post',
- { test: 'proxy demo', timestamp: Date.now() },
- { timeout: 10000, retries: 1 },
- )
- console.log(`✅ 便捷POST成功`)
- console.log(` 收到数据键: ${Object.keys(postData.json || {}).join(', ')}`)
- } catch (error: any) {
- console.error(`❌ 便捷方法测试失败: ${error.message}`)
- }
- }
- // 6. 会话管理演示
- console.log('\n🎲 第六步: 会话管理演示...')
- if (Config.proxy.aster.sessionPrefix() && Config.proxy.aster.sessionSuffix()) {
- console.log('演示多个会话ID生成...')
- for (let i = 0; i < 3; i++) {
- const sessionId = Config.proxy.generateSessionId()
- const password = Config.proxy.buildPassword('aster')
- console.log(` 会话 ${i + 1}: ${sessionId} -> ${password?.substring(0, 20)}...`)
- }
- } else {
- console.log('未配置会话管理,跳过演示')
- }
- console.log('\n🎉 代理配置演示完成!')
- console.log('\n💡 主要特性:')
- console.log(' 🔹 支持全局代理和交易所专用代理')
- console.log(' 🔹 高级会话管理 (前缀+随机ID+后缀)')
- console.log(' 🔹 自动重试和错误处理')
- console.log(' 🔹 完整的代理URL构建')
- console.log(' 🔹 兼容原生fetch API')
- console.log(' 🔹 详细的请求日志')
- } catch (error: any) {
- console.error('❌ 代理演示失败:', error)
- logger.error('代理演示失败', { error: error.message })
- }
- }
- /**
- * 遮蔽代理URL中的敏感信息
- */
- function maskProxyUrl(url: string): string {
- try {
- const urlObj = new URL(url)
- if (urlObj.username && urlObj.password) {
- const maskedUsername = urlObj.username.substring(0, 4) + '***'
- const maskedPassword = '***' + urlObj.password.substring(urlObj.password.length - 4)
- return `${urlObj.protocol}//${maskedUsername}:${maskedPassword}@${urlObj.host}`
- }
- return url
- } catch {
- return url
- }
- }
- /**
- * 显示配置帮助
- */
- function showProxyHelp() {
- console.log('\n💡 代理配置说明:')
- console.log(`
- # 1. 全局代理配置
- PROXY_ENABLED=true
- PROXY_PROTOCOL=http
- PROXY_HOST=proxy.example.com
- PROXY_PORT=8080
- PROXY_USERNAME=username
- PROXY_PASSWORD=password
- # 2. 高级会话管理
- PROXY_SESSION_PREFIX=prefix_
- PROXY_SESSION_SUFFIX=_suffix
- PROXY_SESSION_STATIC=fixed123 # 可选,固定会话ID
- # 3. Aster专用代理 (优先级更高)
- ASTER_PROXY_PROTOCOL=http
- ASTER_PROXY_HOST=geo.iproyal.com
- ASTER_PROXY_PORT=12321
- ASTER_PROXY_USER=tuxla
- ASTER_PROXY_PASS=complete_password # 方式一:直接密码
- # 或使用会话管理 (方式二)
- ASTER_PROXY_SESSION_PREFIX=test123456_country-jp,sg_session-
- ASTER_PROXY_SESSION_SUFFIX=_lifetime-59m
- ASTER_PROXY_SESSION_STATIC=fixed123 # 可选
- # 4. 代码中使用
- import { httpClient } from '../src/utils/httpClient'
- // 使用全局代理
- await httpClient.get('https://api.example.com')
- // 使用Aster专用代理
- await httpClient.get('https://fapi.asterdex.com/info', { exchange: 'aster' })
- `)
- }
- // 运行演示
- if (import.meta.url === `file://${process.argv[1]}`) {
- if (process.argv.includes('--help') || process.argv.includes('-h')) {
- showProxyHelp()
- } else {
- proxyDemo()
- }
- }
|