mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 21:17:30 +00:00
chore: 去除claude转发冗余代码
This commit is contained in:
@@ -1876,156 +1876,6 @@ class ClaudeRelayService {
|
||||
})
|
||||
}
|
||||
|
||||
// 🌊 发送流式请求到Claude API
|
||||
async _makeClaudeStreamRequest(
|
||||
body,
|
||||
accessToken,
|
||||
proxyAgent,
|
||||
clientHeaders,
|
||||
responseStream,
|
||||
requestOptions = {}
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = new URL(this.claudeApiUrl)
|
||||
|
||||
// 获取过滤后的客户端 headers
|
||||
const filteredHeaders = this._filterClientHeaders(clientHeaders)
|
||||
|
||||
const options = {
|
||||
hostname: url.hostname,
|
||||
port: url.port || 443,
|
||||
path: url.pathname,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'anthropic-version': this.apiVersion,
|
||||
...filteredHeaders
|
||||
},
|
||||
agent: proxyAgent,
|
||||
timeout: config.requestTimeout || 600000
|
||||
}
|
||||
|
||||
// 如果客户端没有提供 User-Agent,使用默认值
|
||||
if (!filteredHeaders['User-Agent'] && !filteredHeaders['user-agent']) {
|
||||
// 第三个方法不支持统一 User-Agent,使用简化逻辑
|
||||
const userAgent =
|
||||
clientHeaders?.['user-agent'] ||
|
||||
clientHeaders?.['User-Agent'] ||
|
||||
'claude-cli/1.0.102 (external, cli)'
|
||||
options.headers['User-Agent'] = userAgent
|
||||
}
|
||||
|
||||
// 使用自定义的 betaHeader 或默认值
|
||||
const betaHeader =
|
||||
requestOptions?.betaHeader !== undefined ? requestOptions.betaHeader : this.betaHeader
|
||||
if (betaHeader) {
|
||||
options.headers['anthropic-beta'] = betaHeader
|
||||
}
|
||||
|
||||
const req = https.request(options, (res) => {
|
||||
// 设置响应头
|
||||
responseStream.statusCode = res.statusCode
|
||||
Object.keys(res.headers).forEach((key) => {
|
||||
responseStream.setHeader(key, res.headers[key])
|
||||
})
|
||||
|
||||
// 管道响应数据
|
||||
res.pipe(responseStream)
|
||||
|
||||
res.on('end', () => {
|
||||
logger.debug('🌊 Claude stream response completed')
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
req.on('error', async (error) => {
|
||||
logger.error(`❌ Claude stream request error:`, error.message, {
|
||||
code: error.code,
|
||||
errno: error.errno,
|
||||
syscall: error.syscall
|
||||
})
|
||||
|
||||
// 根据错误类型提供更具体的错误信息
|
||||
let errorMessage = 'Upstream request failed'
|
||||
let statusCode = 500
|
||||
if (error.code === 'ECONNRESET') {
|
||||
errorMessage = 'Connection reset by Claude API server'
|
||||
statusCode = 502
|
||||
} else if (error.code === 'ENOTFOUND') {
|
||||
errorMessage = 'Unable to resolve Claude API hostname'
|
||||
statusCode = 502
|
||||
} else if (error.code === 'ECONNREFUSED') {
|
||||
errorMessage = 'Connection refused by Claude API server'
|
||||
statusCode = 502
|
||||
} else if (error.code === 'ETIMEDOUT') {
|
||||
errorMessage = 'Connection timed out to Claude API server'
|
||||
statusCode = 504
|
||||
}
|
||||
|
||||
if (!responseStream.headersSent) {
|
||||
responseStream.writeHead(statusCode, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
Connection: 'keep-alive'
|
||||
})
|
||||
}
|
||||
|
||||
if (!responseStream.destroyed) {
|
||||
// 发送 SSE 错误事件
|
||||
responseStream.write('event: error\n')
|
||||
responseStream.write(
|
||||
`data: ${JSON.stringify({
|
||||
error: errorMessage,
|
||||
code: error.code,
|
||||
timestamp: new Date().toISOString()
|
||||
})}\n\n`
|
||||
)
|
||||
responseStream.end()
|
||||
}
|
||||
reject(error)
|
||||
})
|
||||
|
||||
req.on('timeout', async () => {
|
||||
req.destroy()
|
||||
logger.error(`❌ Claude stream request timeout`)
|
||||
|
||||
if (!responseStream.headersSent) {
|
||||
responseStream.writeHead(504, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
Connection: 'keep-alive'
|
||||
})
|
||||
}
|
||||
if (!responseStream.destroyed) {
|
||||
// 发送 SSE 错误事件
|
||||
responseStream.write('event: error\n')
|
||||
responseStream.write(
|
||||
`data: ${JSON.stringify({
|
||||
error: 'Request timeout',
|
||||
code: 'TIMEOUT',
|
||||
timestamp: new Date().toISOString()
|
||||
})}\n\n`
|
||||
)
|
||||
responseStream.end()
|
||||
}
|
||||
reject(new Error('Request timeout'))
|
||||
})
|
||||
|
||||
// 处理客户端断开连接
|
||||
responseStream.on('close', () => {
|
||||
logger.debug('🔌 Client disconnected, cleaning up stream')
|
||||
if (!req.destroyed) {
|
||||
req.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
// 写入请求体
|
||||
req.write(JSON.stringify(body))
|
||||
req.end()
|
||||
})
|
||||
}
|
||||
|
||||
// 🛠️ 统一的错误处理方法
|
||||
async _handleServerError(accountId, statusCode, _sessionHash = null, context = '') {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user