Files
NetworkAuth/utils/errors.go

255 lines
7.8 KiB
Go
Raw Normal View History

2025-10-24 00:09:45 +08:00
package utils
import (
"encoding/json"
"fmt"
"log"
"runtime"
"time"
2025-10-26 14:48:02 +08:00
"github.com/gin-gonic/gin"
2025-10-24 00:09:45 +08:00
"gorm.io/gorm"
)
// ErrorResponse 统一的错误响应结构
// 用于标准化API错误响应格式
type ErrorResponse struct {
Success bool `json:"success"` // 请求是否成功错误响应时固定为false
Message string `json:"message"` // 错误消息描述
ErrorCode string `json:"error_code,omitempty"` // 错误代码,用于客户端识别错误类型
Data interface{} `json:"data"` // 附加数据,可为空
Timestamp int64 `json:"timestamp"` // 响应时间戳
}
// SuccessResponse 统一的成功响应结构
// 用于标准化API成功响应格式
type SuccessResponse struct {
Success bool `json:"success"` // 请求是否成功成功响应时固定为true
Message string `json:"message"` // 成功消息描述
Data interface{} `json:"data"` // 响应数据
Timestamp int64 `json:"timestamp"` // 响应时间戳
}
// ErrorCode 错误代码常量
// 定义标准化的错误代码,用于客户端识别和处理不同类型的错误
const (
ErrCodeInvalidRequest = "INVALID_REQUEST" // 无效请求,通常是请求参数格式错误
ErrCodeUnauthorized = "UNAUTHORIZED" // 未授权需要登录或token无效
ErrCodeForbidden = "FORBIDDEN" // 禁止访问,权限不足
ErrCodeNotFound = "NOT_FOUND" // 资源不存在
ErrCodeConflict = "CONFLICT" // 资源冲突,如重复创建
ErrCodeInternalError = "INTERNAL_ERROR" // 服务器内部错误
ErrCodeDatabaseError = "DATABASE_ERROR" // 数据库操作错误
ErrCodeValidationError = "VALIDATION_ERROR" // 数据验证错误
ErrCodeTokenExpired = "TOKEN_EXPIRED" // 令牌已过期
ErrCodeInsufficientData = "INSUFFICIENT_DATA" // 数据不足,缺少必要信息
)
// LogLevel 日志级别
// 定义不同的日志记录级别
type LogLevel int
const (
LogLevelInfo LogLevel = iota // 信息级别,记录一般信息
LogLevelWarn // 警告级别,记录潜在问题
LogLevelError // 错误级别,记录错误信息
LogLevelDebug // 调试级别,记录调试信息
)
// LogEntry 日志条目结构
// 包含完整的日志信息,用于结构化日志记录
type LogEntry struct {
Level LogLevel `json:"level"` // 日志级别
Message string `json:"message"` // 日志消息
Error string `json:"error,omitempty"` // 错误信息,仅在错误日志中存在
Context interface{} `json:"context,omitempty"` // 上下文信息,额外的结构化数据
Timestamp time.Time `json:"timestamp"` // 日志时间戳
File string `json:"file"` // 源文件路径
Line int `json:"line"` // 源文件行号
}
// WriteErrorResponse 写入错误响应
2025-10-26 14:48:02 +08:00
// c: Gin上下文
2025-10-24 00:09:45 +08:00
// statusCode: HTTP状态码
// message: 错误消息
// errorCode: 错误代码
// data: 附加数据
2025-10-26 14:48:02 +08:00
func WriteErrorResponse(c *gin.Context, statusCode int, message, errorCode string, data interface{}) {
2025-10-24 00:09:45 +08:00
response := ErrorResponse{
Success: false,
Message: message,
ErrorCode: errorCode,
Data: data,
Timestamp: time.Now().Unix(),
}
2025-10-26 14:48:02 +08:00
c.JSON(statusCode, response)
2025-10-24 00:09:45 +08:00
}
// WriteSuccessResponse 写入成功响应
2025-10-26 14:48:02 +08:00
// c: Gin上下文
2025-10-24 00:09:45 +08:00
// statusCode: HTTP状态码
// message: 成功消息
// data: 响应数据
2025-10-26 14:48:02 +08:00
func WriteSuccessResponse(c *gin.Context, statusCode int, message string, data interface{}) {
2025-10-24 00:09:45 +08:00
response := SuccessResponse{
Success: true,
Message: message,
Data: data,
Timestamp: time.Now().Unix(),
}
2025-10-26 14:48:02 +08:00
c.JSON(statusCode, response)
2025-10-24 00:09:45 +08:00
}
// HandleDatabaseError 处理数据库错误
2025-10-26 14:48:02 +08:00
// c: Gin上下文
2025-10-24 00:09:45 +08:00
// err: 数据库错误
// operation: 操作描述
2025-10-26 14:48:02 +08:00
func HandleDatabaseError(c *gin.Context, err error, operation string) {
2025-10-24 00:09:45 +08:00
if err == gorm.ErrRecordNotFound {
LogWarn(fmt.Sprintf("Record not found during %s", operation), map[string]interface{}{
"operation": operation,
"error": err.Error(),
})
2025-10-26 14:48:02 +08:00
WriteErrorResponse(c, 404, "记录不存在", ErrCodeNotFound, nil)
2025-10-24 00:09:45 +08:00
return
}
LogError(fmt.Sprintf("Database error during %s", operation), err, map[string]interface{}{
"operation": operation,
})
2025-10-26 14:48:02 +08:00
WriteErrorResponse(c, 500, "数据库操作失败", ErrCodeDatabaseError, nil)
2025-10-24 00:09:45 +08:00
}
// HandleValidationError 处理验证错误
2025-10-26 14:48:02 +08:00
// c: Gin上下文
2025-10-24 00:09:45 +08:00
// message: 验证错误消息
// details: 验证错误详情
2025-10-26 14:48:02 +08:00
func HandleValidationError(c *gin.Context, message string, details interface{}) {
2025-10-24 00:09:45 +08:00
LogWarn("Validation error: "+message, map[string]interface{}{
"details": details,
})
2025-10-26 14:48:02 +08:00
WriteErrorResponse(c, 400, message, ErrCodeValidationError, details)
2025-10-24 00:09:45 +08:00
}
// HandleUnauthorizedError 处理未授权错误
2025-10-26 14:48:02 +08:00
// c: Gin上下文
2025-10-24 00:09:45 +08:00
// message: 错误消息
2025-10-26 14:48:02 +08:00
func HandleUnauthorizedError(c *gin.Context, message string) {
2025-10-24 00:09:45 +08:00
LogWarn("Unauthorized access: "+message, nil)
2025-10-26 14:48:02 +08:00
WriteErrorResponse(c, 401, message, ErrCodeUnauthorized, nil)
2025-10-24 00:09:45 +08:00
}
// HandleInternalError 处理内部错误
2025-10-26 14:48:02 +08:00
// c: Gin上下文
2025-10-24 00:09:45 +08:00
// err: 错误
// operation: 操作描述
2025-10-26 14:48:02 +08:00
func HandleInternalError(c *gin.Context, err error, operation string) {
2025-10-24 00:09:45 +08:00
LogError(fmt.Sprintf("Internal error during %s", operation), err, map[string]interface{}{
"operation": operation,
})
2025-10-26 14:48:02 +08:00
WriteErrorResponse(c, 500, "服务器内部错误", ErrCodeInternalError, nil)
2025-10-24 00:09:45 +08:00
}
// LogInfo 记录信息日志
// message: 日志消息
// context: 上下文信息
func LogInfo(message string, context interface{}) {
logEntry := createLogEntry(LogLevelInfo, message, nil, context)
printLog(logEntry)
}
// LogWarn 记录警告日志
// message: 日志消息
// context: 上下文信息
func LogWarn(message string, context interface{}) {
logEntry := createLogEntry(LogLevelWarn, message, nil, context)
printLog(logEntry)
}
// LogError 记录错误日志
// message: 日志消息
// err: 错误对象
// context: 上下文信息
func LogError(message string, err error, context interface{}) {
errorStr := ""
if err != nil {
errorStr = err.Error()
}
logEntry := createLogEntry(LogLevelError, message, &errorStr, context)
printLog(logEntry)
}
// LogDebug 记录调试日志
// message: 日志消息
// context: 上下文信息
func LogDebug(message string, context interface{}) {
logEntry := createLogEntry(LogLevelDebug, message, nil, context)
printLog(logEntry)
}
// createLogEntry 创建日志条目
// level: 日志级别
// message: 日志消息
// errorStr: 错误字符串
// context: 上下文信息
// 返回: 日志条目
func createLogEntry(level LogLevel, message string, errorStr *string, context interface{}) LogEntry {
_, file, line, _ := runtime.Caller(2)
entry := LogEntry{
Level: level,
Message: message,
Context: context,
Timestamp: time.Now(),
File: file,
Line: line,
}
if errorStr != nil {
entry.Error = *errorStr
}
return entry
}
// printLog 打印日志
// entry: 日志条目
func printLog(entry LogEntry) {
levelStr := getLevelString(entry.Level)
timestamp := entry.Timestamp.Format("2006-01-02 15:04:05")
logMessage := fmt.Sprintf("[%s] %s %s", levelStr, timestamp, entry.Message)
if entry.Error != "" {
logMessage += fmt.Sprintf(" | Error: %s", entry.Error)
}
if entry.Context != nil {
contextJSON, _ := json.Marshal(entry.Context)
logMessage += fmt.Sprintf(" | Context: %s", string(contextJSON))
}
logMessage += fmt.Sprintf(" | %s:%d", entry.File, entry.Line)
log.Println(logMessage)
}
// getLevelString 获取日志级别字符串
// level: 日志级别
// 返回: 级别字符串
func getLevelString(level LogLevel) string {
switch level {
case LogLevelInfo:
return "INFO"
case LogLevelWarn:
return "WARN"
case LogLevelError:
return "ERROR"
case LogLevelDebug:
return "DEBUG"
default:
return "UNKNOWN"
}
}