Files
gpt-load/internal/errors/errors.go
2025-07-07 18:55:06 +08:00

71 lines
2.7 KiB
Go

package errors
import (
"errors"
"net/http"
"github.com/go-sql-driver/mysql"
"gorm.io/gorm"
)
// APIError defines a standard error structure for API responses.
type APIError struct {
HTTPStatus int
Code string
Message string
}
// Error implements the error interface.
func (e *APIError) Error() string {
return e.Message
}
// Predefined API errors
var (
ErrBadRequest = &APIError{HTTPStatus: http.StatusBadRequest, Code: "BAD_REQUEST", Message: "Invalid request parameters"}
ErrInvalidJSON = &APIError{HTTPStatus: http.StatusBadRequest, Code: "INVALID_JSON", Message: "Invalid JSON format"}
ErrValidation = &APIError{HTTPStatus: http.StatusBadRequest, Code: "VALIDATION_FAILED", Message: "Input validation failed"}
ErrDuplicateResource = &APIError{HTTPStatus: http.StatusConflict, Code: "DUPLICATE_RESOURCE", Message: "Resource already exists"}
ErrResourceNotFound = &APIError{HTTPStatus: http.StatusNotFound, Code: "NOT_FOUND", Message: "Resource not found"}
ErrInternalServer = &APIError{HTTPStatus: http.StatusInternalServerError, Code: "INTERNAL_SERVER_ERROR", Message: "An unexpected error occurred"}
ErrDatabase = &APIError{HTTPStatus: http.StatusInternalServerError, Code: "DATABASE_ERROR", Message: "Database operation failed"}
ErrUnauthorized = &APIError{HTTPStatus: http.StatusUnauthorized, Code: "UNAUTHORIZED", Message: "Authentication failed"}
ErrForbidden = &APIError{HTTPStatus: http.StatusForbidden, Code: "FORBIDDEN", Message: "You do not have permission to access this resource"}
ErrTaskInProgress = &APIError{HTTPStatus: http.StatusConflict, Code: "TASK_IN_PROGRESS", Message: "A task is already in progress"}
ErrBadGateway = &APIError{HTTPStatus: http.StatusBadGateway, Code: "BAD_GATEWAY", Message: "Upstream service error"}
ErrNoActiveKeys = &APIError{HTTPStatus: http.StatusServiceUnavailable, Code: "NO_ACTIVE_KEYS", Message: "No active API keys available for this group"}
)
// NewAPIError creates a new APIError with a custom message.
func NewAPIError(base *APIError, message string) *APIError {
return &APIError{
HTTPStatus: base.HTTPStatus,
Code: base.Code,
Message: message,
}
}
// ParseDBError intelligently converts a GORM error into a standard APIError.
func ParseDBError(err error) *APIError {
if err == nil {
return nil
}
// Handle record not found error
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrResourceNotFound
}
// Handle MySQL specific errors
var mysqlErr *mysql.MySQLError
if errors.As(err, &mysqlErr) {
switch mysqlErr.Number {
case 1062: // Duplicate entry for unique key
return ErrDuplicateResource
}
}
// Default to a generic database error
return ErrDatabase
}