File size: 4,929 Bytes
c666a95 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
const logger = require('./logger')
/**
* 公共错误处理工具类
* 提供统一的错误处理和响应格式
*/
class ErrorHandler {
/**
* 处理 API 错误响应
* @param {Object} res - Express 响应对象
* @param {Error} error - 错误对象
* @param {string} requestId - 请求ID
* @param {Object} context - 错误上下文信息
*/
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
}
})
}
/**
* 处理模型调用错误
* @param {Object} res - Express 响应对象
* @param {Error} error - 错误对象
* @param {string} requestId - 请求ID
* @param {string} model - 模型名称
* @param {boolean} isStream - 是否为流式请求
*/
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
})
// 特殊处理403错误(使用限制)
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
}
})
}
/**
* 处理使用限制错误
* @param {Object} res - Express 响应对象
* @param {string} requestId - 请求ID
* @param {string} model - 模型名称
*/
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'
}
})
}
/**
* 处理图片上传错误
* @param {string} requestId - 请求ID
* @param {Error} error - 错误对象
* @param {Object} context - 上下文信息
*/
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}`)
}
/**
* 解析错误对象,提取关键信息
* @param {Error} error - 错误对象
* @returns {Object} 解析后的错误信息
*/
static parseError(error) {
let statusCode = 500
let message = '服务器内部错误'
let type = 'server_error'
let code = 'internal_error'
if (error.response) {
// Axios 错误
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
}
}
/**
* 创建标准化错误对象
* @param {string} message - 错误消息
* @param {number} statusCode - HTTP状态码
* @param {string} type - 错误类型
* @param {string} code - 错误代码
* @returns {Error} 标准化错误对象
*/
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
|