|
|
const logger = require('./logger') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ErrorHandler { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static handleApiError(res, error, requestId = null, context = {}) { |
|
|
const errorInfo = this.parseError(error) |
|
|
|
|
|
|
|
|
if (requestId) { |
|
|
logger.logError(requestId, 'API_ERROR', errorInfo.message, { |
|
|
...context, |
|
|
statusCode: errorInfo.statusCode, |
|
|
errorType: errorInfo.type |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
res.status(errorInfo.statusCode).json({ |
|
|
error: { |
|
|
message: errorInfo.message, |
|
|
type: errorInfo.type, |
|
|
code: errorInfo.code |
|
|
} |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static handleModelError(res, error, requestId, model, isStream = false) { |
|
|
const errorInfo = this.parseError(error) |
|
|
|
|
|
logger.logError(requestId, 'MODEL_CALL_ERROR', errorInfo.message, { |
|
|
model, |
|
|
isStream, |
|
|
statusCode: errorInfo.statusCode, |
|
|
errorType: errorInfo.type |
|
|
}) |
|
|
|
|
|
|
|
|
if (errorInfo.statusCode === 403) { |
|
|
return this.handleRateLimitError(res, requestId, model) |
|
|
} |
|
|
|
|
|
|
|
|
res.status(errorInfo.statusCode).json({ |
|
|
error: { |
|
|
message: errorInfo.message, |
|
|
type: errorInfo.type, |
|
|
code: errorInfo.code |
|
|
} |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static handleRateLimitError(res, requestId, model) { |
|
|
const errorMessage = `模型 ${model} 已达到使用限制,请稍后再试` |
|
|
|
|
|
logger.logError(requestId, 'RATE_LIMIT_ERROR', errorMessage, { |
|
|
model, |
|
|
statusCode: 429 |
|
|
}) |
|
|
|
|
|
res.status(429).json({ |
|
|
error: { |
|
|
message: errorMessage, |
|
|
type: 'rate_limit_exceeded', |
|
|
code: 'rate_limit_exceeded' |
|
|
} |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static handleImageUploadError(requestId, error, context = {}) { |
|
|
const errorInfo = this.parseError(error) |
|
|
|
|
|
logger.logError(requestId, 'IMAGE_UPLOAD_ERROR', errorInfo.message, { |
|
|
...context, |
|
|
errorType: errorInfo.type |
|
|
}) |
|
|
|
|
|
throw new Error(`图片上传失败: ${errorInfo.message}`) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static parseError(error) { |
|
|
let statusCode = 500 |
|
|
let message = '服务器内部错误' |
|
|
let type = 'server_error' |
|
|
let code = 'internal_error' |
|
|
|
|
|
if (error.response) { |
|
|
|
|
|
statusCode = error.response.status || 500 |
|
|
message = error.response.data?.message || |
|
|
error.response.data?.statusMessage || |
|
|
error.message || |
|
|
'请求失败' |
|
|
|
|
|
if (statusCode === 403) { |
|
|
type = 'rate_limit_exceeded' |
|
|
code = 'rate_limit_exceeded' |
|
|
} else if (statusCode === 401) { |
|
|
type = 'authentication_error' |
|
|
code = 'invalid_api_key' |
|
|
} else if (statusCode >= 400 && statusCode < 500) { |
|
|
type = 'client_error' |
|
|
code = 'bad_request' |
|
|
} |
|
|
} else if (error.code) { |
|
|
|
|
|
if (error.code === 'ECONNREFUSED') { |
|
|
message = '连接被拒绝' |
|
|
type = 'connection_error' |
|
|
code = 'connection_refused' |
|
|
} else if (error.code === 'ETIMEDOUT') { |
|
|
message = '请求超时' |
|
|
type = 'timeout_error' |
|
|
code = 'request_timeout' |
|
|
statusCode = 408 |
|
|
} |
|
|
} else { |
|
|
|
|
|
message = error.message || '未知错误' |
|
|
} |
|
|
|
|
|
return { |
|
|
statusCode, |
|
|
message, |
|
|
type, |
|
|
code |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static createError(message, statusCode = 500, type = 'server_error', code = 'internal_error') { |
|
|
const error = new Error(message) |
|
|
error.statusCode = statusCode |
|
|
error.type = type |
|
|
error.code = code |
|
|
return error |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = ErrorHandler |
|
|
|