版本: 1.0.0 创建日期: 2025-09-28 目标: 提供HTTP客户端库的快速开始指南和使用示例
# 安装HTTP客户端库
npm install @yourorg/http-client
# 安装依赖(如果单独使用)
npm install @yourorg/credential-manager winston https-proxy-agent
创建 .env
文件:
# Pacifica DEX配置
PACIFICA_ACCOUNT_ID=your_pacifica_account
PACIFICA_PRIVATE_KEY=your_pacifica_private_key
# Aster DEX配置
ASTER_ACCOUNT_ID=0x_your_aster_account
ASTER_PRIVATE_KEY=0x_your_aster_private_key
# Binance配置
BINANCE_API_KEY=your_binance_api_key
BINANCE_SECRET_KEY=your_binance_secret_key
# 可选:代理配置
HTTP_PROXY_URL=http://username:password@proxy.server.com:8080
import { UniversalHttpClient } from '@yourorg/http-client'
// 创建客户端实例
const httpClient = new UniversalHttpClient({
timeout: {
connect: 5000,
read: 30000,
write: 15000
},
retry: {
maxAttempts: 3,
exponentialBackoff: true
},
enableLogging: true
})
// 添加账户
await httpClient.addAccount('pacifica', 'main-account', {
accountId: process.env.PACIFICA_ACCOUNT_ID!,
privateKey: process.env.PACIFICA_PRIVATE_KEY!
})
// 发起API请求
const response = await httpClient.request({
platform: 'pacifica',
accountId: 'main-account',
method: 'GET',
url: '/api/v1/account/info'
})
console.log('账户信息:', response.data)
目标: 查询所有平台账户的余额信息
import { UniversalHttpClient } from '@yourorg/http-client'
async function queryAllBalances() {
const client = new UniversalHttpClient()
// 配置多个平台账户
await client.addAccount('pacifica', 'pac-main', {
accountId: process.env.PACIFICA_ACCOUNT_ID!,
privateKey: process.env.PACIFICA_PRIVATE_KEY!
})
await client.addAccount('aster', 'ast-main', {
accountId: process.env.ASTER_ACCOUNT_ID!,
privateKey: process.env.ASTER_PRIVATE_KEY!
})
await client.addAccount('binance', 'bnc-main', {
apiKey: process.env.BINANCE_API_KEY!,
secretKey: process.env.BINANCE_SECRET_KEY!
})
// 并发查询所有平台余额
const requests = [
{
platform: 'pacifica' as const,
accountId: 'pac-main',
method: 'GET' as const,
url: '/api/v1/account/info'
},
{
platform: 'aster' as const,
accountId: 'ast-main',
method: 'GET' as const,
url: '/api/v1/account/balance'
},
{
platform: 'binance' as const,
accountId: 'bnc-main',
method: 'GET' as const,
url: '/api/v3/account'
}
]
// 批量执行请求
const responses = await client.batchRequest(requests)
// 处理结果
responses.forEach((response, index) => {
const platform = requests[index].platform
console.log(`${platform} 余额:`, response.data)
})
await client.close()
}
// 运行示例
queryAllBalances().catch(console.error)
预期输出:
pacifica 余额: { totalBalance: 1500.50, availableBalance: 1200.30, ... }
aster 余额: { balance: 2300.75, lockedBalance: 100.25, ... }
binance 余额: { balances: [{ asset: 'USDT', free: '1000.00', ... }] }
目标: 在不同平台下单,处理平台特定的认证和格式要求
import { UniversalHttpClient } from '@yourorg/http-client'
async function placeOrdersAcrossPlatforms() {
const client = new UniversalHttpClient({
retry: {
maxAttempts: 3,
shouldRetry: (error) => {
// 认证错误不重试,网络错误重试
return error.code !== 'AUTH_FAILED'
}
}
})
// 添加账户
await client.addAccount('pacifica', 'trading', {
accountId: process.env.PACIFICA_ACCOUNT_ID!,
privateKey: process.env.PACIFICA_PRIVATE_KEY!
})
await client.addAccount('aster', 'trading', {
accountId: process.env.ASTER_ACCOUNT_ID!,
privateKey: process.env.ASTER_PRIVATE_KEY!
})
try {
// Pacifica 限价单
const pacificaOrder = await client.request({
platform: 'pacifica',
accountId: 'trading',
method: 'POST',
url: '/api/v1/order/limit',
body: {
symbol: 'BTC-USD',
side: 'buy',
amount: 0.001,
price: 65000,
timeInForce: 'GTC'
},
options: {
timeout: { read: 10000 },
idempotencyKey: `pac-order-${Date.now()}`
}
})
console.log('Pacifica订单成功:', pacificaOrder.data.orderId)
// Aster 市价单
const asterOrder = await client.request({
platform: 'aster',
accountId: 'trading',
method: 'POST',
url: '/api/v1/orders',
body: {
symbol: 'BTCUSDT',
side: 'BUY',
type: 'MARKET',
quantity: 0.001
},
options: {
timeout: { read: 15000 },
idempotencyKey: `ast-order-${Date.now()}`
}
})
console.log('Aster订单成功:', asterOrder.data.orderId)
} catch (error) {
if (error.code === 'AUTH_FAILED') {
console.error('认证失败,请检查凭据配置')
} else if (error.code === 'RATE_LIMITED') {
console.error('触发速率限制,请稍后重试')
} else {
console.error('订单失败:', error.message)
}
}
await client.close()
}
placeOrdersAcrossPlatforms().catch(console.error)
目标: 灵活控制代理开关,使用高级代理配置进行网络隔离
import { UniversalHttpClient } from '@yourorg/http-client'
async function proxyAdvancedConfiguration() {
const client = new UniversalHttpClient({
// 全局代理配置
globalProxy: {
enabled: true,
url: process.env.HTTP_PROXY_URL,
type: 'http',
auth: {
username: process.env.PROXY_USERNAME!,
password: process.env.PROXY_PASSWORD!
},
pool: {
servers: [
'http://proxy1.example.com:8080',
'http://proxy2.example.com:8080',
'http://proxy3.example.com:8080'
],
strategy: 'round-robin',
healthCheckUrl: 'http://httpbin.org/ip',
healthCheckInterval: 60000
},
failover: {
enabled: true,
maxRetries: 3,
delay: 1000,
fallbackToDirect: false // 不允许直连回退
}
}
})
// 添加账户(使用全局代理)
await client.addAccount('pacifica', 'global-proxy-account', {
accountId: process.env.PACIFICA_ACCOUNT_ID!,
privateKey: process.env.PACIFICA_PRIVATE_KEY!
})
// 添加账户(禁用代理)
await client.addAccount('aster', 'no-proxy-account', {
accountId: process.env.ASTER_ACCOUNT_ID!,
privateKey: process.env.ASTER_PRIVATE_KEY!,
proxyDisabled: true // 账户级别禁用代理
})
try {
console.log('=== 代理开关测试 ===')
// 1. 使用全局代理(默认行为)
console.log('\\n1. 使用全局代理配置:')
const response1 = await client.request({
platform: 'pacifica',
accountId: 'global-proxy-account',
method: 'GET',
url: '/api/v1/market/prices',
options: {
proxy: { strategy: 'global' } // 明确使用全局代理
}
})
console.log('- 响应时间:', response1.metadata.duration, 'ms')
console.log('- 使用代理:', response1.metadata.usedProxy)
// 2. 强制使用特定代理
console.log('\\n2. 强制使用特定代理:')
const response2 = await client.request({
platform: 'pacifica',
accountId: 'global-proxy-account',
method: 'GET',
url: '/api/v1/account/info',
options: {
proxy: {
strategy: 'force',
forceProxy: {
enabled: true,
url: 'http://special-proxy.example.com:8080',
type: 'http',
auth: {
username: 'special-user',
password: 'special-pass'
},
session: {
prefix: 'force-session-',
suffix: '_custom',
rotation: false,
sticky: true
}
}
}
}
})
console.log('- 使用的代理:', response2.metadata.proxyUsed)
// 3. 临时禁用代理
console.log('\\n3. 临时禁用代理(直连):')
const response3 = await client.request({
platform: 'pacifica',
accountId: 'global-proxy-account',
method: 'GET',
url: '/api/v1/market/tickers',
options: {
proxy: {
strategy: 'disabled',
disableProxy: true
}
}
})
console.log('- 使用代理:', response3.metadata.usedProxy)
console.log('- 直连响应时间:', response3.metadata.duration, 'ms')
// 4. 账户级别禁用代理的测试
console.log('\\n4. 账户级别禁用代理:')
const response4 = await client.request({
platform: 'aster',
accountId: 'no-proxy-account',
method: 'GET',
url: '/api/v1/market/tickers'
// 即使不指定proxy选项,该账户也不会使用代理
})
console.log('- 使用代理:', response4.metadata.usedProxy)
// 5. 代理轮换测试
console.log('\\n5. 代理轮换测试:')
for (let i = 0; i < 3; i++) {
const response = await client.request({
platform: 'pacifica',
accountId: 'global-proxy-account',
method: 'GET',
url: '/api/v1/market/prices',
options: {
proxy: {
strategy: 'global',
rotation: {
enabled: true,
interval: 1, // 每次请求轮换
strategy: 'round-robin'
}
}
}
})
console.log(`- 第${i+1}次请求代理:`, response.metadata.proxyUsed)
}
// 6. 代理健康检查
console.log('\\n6. 代理健康检查:')
const proxyStatus = await client.getProxyStatus()
console.log('代理池状态:', {
总代理数: proxyStatus.pool?.totalProxies,
活跃代理数: proxyStatus.pool?.activeProxies,
当前代理: proxyStatus.currentProxy,
健康状态: proxyStatus.health.isHealthy,
连续失败次数: proxyStatus.health.consecutiveFailures
})
// 7. 代理故障转移测试
console.log('\\n7. 代理故障转移测试:')
const response7 = await client.request({
platform: 'pacifica',
accountId: 'global-proxy-account',
method: 'GET',
url: '/api/v1/market/depth',
params: { symbol: 'BTC-USD' },
options: {
proxy: {
strategy: 'global',
healthCheck: {
enabled: true,
timeout: 2000,
failureThreshold: 2
}
},
retry: {
maxAttempts: 5, // 增加重试次数以测试故障转移
shouldRetry: (error) => {
return error.code === 'PROXY_ERROR' || error.code === 'TIMEOUT'
}
}
}
})
console.log('- 故障转移成功,响应:', response7.status)
} catch (error) {
console.error('代理配置错误:', {
code: error.code,
message: error.message,
proxyStatus: error.proxyStatus
})
// 代理错误处理
if (error.code === 'PROXY_ERROR') {
console.log('\\n尝试切换到备用代理或直连...')
const fallbackResponse = await client.request({
platform: 'pacifica',
accountId: 'global-proxy-account',
method: 'GET',
url: '/api/v1/market/prices',
options: {
proxy: { strategy: 'disabled' } // 回退到直连
}
})
console.log('直连回退成功:', fallbackResponse.status)
}
}
await client.close()
}
proxyAdvancedConfiguration().catch(console.error)
目标: 监控客户端性能,确保服务质量
import { UniversalHttpClient } from '@yourorg/http-client'
async function performanceMonitoring() {
const client = new UniversalHttpClient({
metrics: {
enabled: true,
collectInterval: 30000, // 30秒收集一次指标
historyRetention: 3600000 // 保留1小时历史
}
})
// 添加多个账户进行测试
await client.addAccount('pacifica', 'test-1', {
accountId: process.env.PACIFICA_ACCOUNT_ID!,
privateKey: process.env.PACIFICA_PRIVATE_KEY!
})
await client.addAccount('aster', 'test-2', {
accountId: process.env.ASTER_ACCOUNT_ID!,
privateKey: process.env.ASTER_PRIVATE_KEY!
})
// 模拟高并发请求
console.log('开始性能测试...')
const startTime = Date.now()
const requests = Array.from({ length: 100 }, (_, i) => ({
platform: i % 2 === 0 ? 'pacifica' as const : 'aster' as const,
accountId: i % 2 === 0 ? 'test-1' : 'test-2',
method: 'GET' as const,
url: i % 2 === 0 ? '/api/v1/market/prices' : '/api/v1/market/tickers'
}))
try {
// 批量执行并发请求
const responses = await client.batchRequest(requests)
const endTime = Date.now()
console.log('性能测试完成:', {
totalRequests: requests.length,
successfulRequests: responses.filter(r => r.ok).length,
totalTime: endTime - startTime,
averageTime: (endTime - startTime) / requests.length
})
// 获取详细健康状态
const health = await client.getHealth()
console.log('系统健康状态:', {
status: health.status,
platforms: Object.entries(health.platforms).map(([name, status]) => ({
platform: name,
status: status.status,
responseTime: status.responseTime,
successRate: status.successRate
})),
metrics: {
totalRequests: health.metrics.totalRequests,
successRate: health.metrics.successfulRequests / health.metrics.totalRequests,
averageResponseTime: health.metrics.averageResponseTime,
p99ResponseTime: health.metrics.p99ResponseTime,
activeConnections: health.metrics.activeConnections
}
})
} catch (error) {
console.error('性能测试失败:', error)
}
await client.close()
}
performanceMonitoring().catch(console.error)
import { UniversalHttpClient } from '@yourorg/http-client'
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'
describe('UniversalHttpClient', () => {
let client: UniversalHttpClient
beforeEach(async () => {
client = new UniversalHttpClient({
timeout: { connect: 1000, read: 5000, write: 3000 }
})
})
afterEach(async () => {
await client.close()
})
it('应该成功添加Pacifica账户', async () => {
await client.addAccount('pacifica', 'test-account', {
accountId: 'test-account-id',
privateKey: 'test-private-key'
})
const health = await client.getHealth()
expect(health.platforms.pacifica).toBeDefined()
})
it('应该处理认证失败错误', async () => {
await client.addAccount('pacifica', 'invalid-account', {
accountId: 'invalid',
privateKey: 'invalid'
})
await expect(client.request({
platform: 'pacifica',
accountId: 'invalid-account',
method: 'GET',
url: '/api/v1/account/info'
})).rejects.toThrow('AUTH_FAILED')
})
it('应该在速率限制时正确重试', async () => {
// 测试重试逻辑
// 实现省略...
})
})
# 运行完整集成测试
npm run test:integration
# 运行特定平台测试
npm run test:pacifica
npm run test:aster
npm run test:binance
# 运行性能基准测试
npm run test:performance
// 1. 全局代理策略(推荐用于生产环境)
const productionConfig = {
proxy: { strategy: 'global' }, // 使用全局配置的代理池
}
// 2. 账户专用代理策略(推荐用于多账户隔离)
const accountConfig = {
proxy: { strategy: 'account' }, // 使用账户专用代理配置
}
// 3. 强制代理策略(推荐用于特殊需求)
const forceConfig = {
proxy: {
strategy: 'force',
forceProxy: {
enabled: true,
url: 'http://special.proxy.com:8080',
type: 'socks5'
}
}
}
// 4. 禁用代理策略(推荐用于调试和测试)
const directConfig = {
proxy: { strategy: 'disabled' }
}
# .env文件配置示例
# 全局代理配置
GLOBAL_PROXY_ENABLED=true
GLOBAL_PROXY_URL=http://proxy.example.com:8080
GLOBAL_PROXY_USERNAME=your_username
GLOBAL_PROXY_PASSWORD=your_password
# 代理池配置
PROXY_POOL_SERVERS=http://proxy1.com:8080,http://proxy2.com:8080,http://proxy3.com:8080
PROXY_POOL_STRATEGY=round-robin
PROXY_HEALTH_CHECK_URL=http://httpbin.org/ip
PROXY_HEALTH_CHECK_INTERVAL=60000
# 账户专用代理配置
PACIFICA_PROXY_ENABLED=true
PACIFICA_PROXY_URL=http://pacifica-proxy.com:8080
PACIFICA_PROXY_SESSION_PREFIX=pac_session_
ASTER_PROXY_ENABLED=false # 禁用Aster账户代理
BINANCE_PROXY_ENABLED=true
BINANCE_PROXY_URL=http://binance-proxy.com:8080
# 故障转移配置
PROXY_FAILOVER_ENABLED=true
PROXY_FAILOVER_MAX_RETRIES=3
PROXY_FAILOVER_DELAY=1000
PROXY_FALLBACK_TO_DIRECT=false # 是否允许直连回退
import { UniversalHttpClient } from '@yourorg/http-client'
// 模式1: 智能代理开关(推荐)
async function smartProxyUsage() {
const client = new UniversalHttpClient({
globalProxy: {
enabled: process.env.GLOBAL_PROXY_ENABLED === 'true',
url: process.env.GLOBAL_PROXY_URL,
// 自动故障转移和健康检查
failover: { enabled: true, fallbackToDirect: false },
pool: { strategy: 'fastest' }
}
})
// 根据操作类型智能选择代理策略
const marketDataResponse = await client.request({
platform: 'pacifica',
accountId: 'main',
method: 'GET',
url: '/api/v1/market/prices',
options: {
proxy: {
strategy: 'global', // 市场数据使用全局代理池
rotation: { enabled: true }
}
}
})
const accountResponse = await client.request({
platform: 'pacifica',
accountId: 'main',
method: 'GET',
url: '/api/v1/account/info',
options: {
proxy: {
strategy: 'account', // 账户数据使用专用代理
healthCheck: { enabled: true }
}
}
})
const tradingResponse = await client.request({
platform: 'pacifica',
accountId: 'main',
method: 'POST',
url: '/api/v1/order/limit',
body: { symbol: 'BTC-USD', side: 'buy', amount: 0.001 },
options: {
proxy: {
strategy: 'force', // 交易操作使用稳定代理
forceProxy: {
enabled: true,
url: process.env.TRADING_PROXY_URL,
connection: { keepAlive: true, timeout: 10000 }
}
}
}
})
}
// 模式2: 条件代理开关
async function conditionalProxyUsage() {
const client = new UniversalHttpClient()
// 根据环境条件动态选择代理策略
const isDevelopment = process.env.NODE_ENV === 'development'
const isHighLatency = await checkNetworkLatency() > 200
const proxyStrategy = isDevelopment
? 'disabled' // 开发环境直连
: isHighLatency
? 'force' // 高延迟强制代理
: 'global' // 正常情况全局代理
const response = await client.request({
platform: 'pacifica',
accountId: 'main',
method: 'GET',
url: '/api/v1/market/depth',
options: { proxy: { strategy: proxyStrategy } }
})
}
// 模式3: 代理性能监控和自动切换
async function performanceBasedProxyUsage() {
const client = new UniversalHttpClient({
globalProxy: {
enabled: true,
pool: {
servers: ['http://fast-proxy.com:8080', 'http://stable-proxy.com:8080'],
strategy: 'fastest', // 自动选择最快代理
healthCheckInterval: 30000
}
}
})
// 性能监控和自动切换
for (let i = 0; i < 10; i++) {
const startTime = Date.now()
try {
const response = await client.request({
platform: 'pacifica',
accountId: 'main',
method: 'GET',
url: '/api/v1/market/prices',
options: {
proxy: {
strategy: 'global',
rotation: { enabled: true, strategy: 'fastest' }
}
}
})
const duration = Date.now() - startTime
console.log(`请求${i+1}: ${duration}ms, 代理: ${response.metadata.proxyUsed}`)
// 如果响应时间过长,切换到直连
if (duration > 1000) {
console.log('代理响应过慢,切换到直连模式')
break
}
} catch (error) {
if (error.code === 'PROXY_ERROR') {
console.log('代理故障,自动切换到备用代理')
// 客户端会自动切换到备用代理
}
}
}
}
async function checkNetworkLatency(): Promise<number> {
// 简单的延迟检测实现
const start = Date.now()
try {
await fetch('http://httpbin.org/delay/0')
return Date.now() - start
} catch {
return 9999 // 网络不可达
}
}
// 启用详细的代理日志
const client = new UniversalHttpClient({
logging: {
level: 'debug',
proxyDetails: true // 记录代理连接详细信息
}
})
// 监听代理事件
client.on('proxy:connect', (proxyUrl) => {
console.log(`代理连接成功: ${proxyUrl}`)
})
client.on('proxy:disconnect', (proxyUrl, reason) => {
console.log(`代理断开连接: ${proxyUrl}, 原因: ${reason}`)
})
client.on('proxy:error', (proxyUrl, error) => {
console.error(`代理错误: ${proxyUrl}`, error)
})
client.on('proxy:switch', (fromProxy, toProxy) => {
console.log(`代理切换: ${fromProxy} -> ${toProxy}`)
})
// 代理状态实时监控
setInterval(async () => {
const status = await client.getProxyStatus()
console.log('代理状态监控:', {
当前代理: status.currentProxy,
连接状态: status.status,
成功率: `${(status.stats.successfulRequests / status.stats.totalRequests * 100).toFixed(1)}%`,
平均响应时间: `${status.stats.averageResponseTime}ms`,
健康状态: status.health.isHealthy ? '健康' : '异常'
})
}, 30000)
认证失败 (AUTH_FAILED)
错误: 签名验证失败
解决: 检查私钥格式和账户ID是否正确
连接超时 (TIMEOUT)
错误: 请求超时
解决: 检查网络连接,调整超时配置
速率限制 (RATE_LIMITED)
错误: 超出API调用限制
解决: 增加请求间隔,实现退避重试
代理连接失败
错误: 代理服务器无响应
解决: 验证代理配置,检查防火墙设置
// 启用详细日志
const client = new UniversalHttpClient({
logging: {
level: 'debug',
sensitiveData: true
}
})
// 查看请求详情
client.on('request', (request) => {
console.log('发送请求:', request.id, request.url)
})
client.on('response', (response) => {
console.log('收到响应:', response.requestId, response.status)
})
client.on('error', (error) => {
console.error('请求错误:', error.code, error.message)
})
// 生产环境配置
const productionConfig = {
timeout: {
connect: 5000,
read: 30000,
write: 15000
},
retry: {
maxAttempts: 3,
exponentialBackoff: true,
delay: 1000
},
connectionPool: {
maxConnectionsPerPlatform: 20,
idleTimeout: 30000,
reuseConnections: true
},
logging: {
level: 'info',
sensitiveData: false, // 生产环境不记录敏感数据
retention: '30d'
}
}
// 设置监控告警
client.on('healthChange', (health) => {
if (health.status === 'unhealthy') {
// 发送告警通知
alertingService.sendAlert('HTTP客户端健康状态异常')
}
})
// 性能监控
setInterval(async () => {
const metrics = await client.getPerformanceMetrics()
if (metrics.averageResponseTime > 100) {
console.warn('响应时间超出目标值')
}
}, 60000)
快速开始总结: 通过以上示例,您可以在15分钟内完成HTTP客户端的基本配置,在1小时内掌握高级功能使用。