136 lines
4 KiB
Go
136 lines
4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"veza-backend-api/internal/errors"
|
|
)
|
|
|
|
// ErrorResponse représente le format d'erreur standardisé selon ORIGIN_API_SPECIFICATION
|
|
// GO-014: Harmonisation format erreurs HTTP
|
|
type ErrorResponse struct {
|
|
Error struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Details []errors.ErrorDetail `json:"details,omitempty"`
|
|
RequestID string `json:"request_id,omitempty"`
|
|
Timestamp string `json:"timestamp"`
|
|
Context map[string]interface{} `json:"context,omitempty"`
|
|
} `json:"error"`
|
|
}
|
|
|
|
// RespondWithAppError répond avec une AppError au format standardisé ORIGIN_API_SPECIFICATION
|
|
// GO-014: Harmonisation format erreurs HTTP selon ORIGIN_API_SPECIFICATION
|
|
func RespondWithAppError(c *gin.Context, appErr *errors.AppError) {
|
|
statusCode := mapErrorCodeToHTTPStatus(appErr.Code)
|
|
|
|
errorData := struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Details []errors.ErrorDetail `json:"details,omitempty"`
|
|
RequestID string `json:"request_id,omitempty"`
|
|
Timestamp string `json:"timestamp"`
|
|
Context map[string]interface{} `json:"context,omitempty"`
|
|
}{
|
|
Code: int(appErr.Code),
|
|
Message: appErr.Message,
|
|
Details: appErr.Details,
|
|
RequestID: c.GetString("request_id"),
|
|
Timestamp: time.Now().UTC().Format(time.RFC3339),
|
|
Context: appErr.Context,
|
|
}
|
|
|
|
c.JSON(statusCode, APIResponse{
|
|
Success: false,
|
|
Data: nil,
|
|
Error: errorData,
|
|
})
|
|
}
|
|
|
|
// RespondWithError répond avec un code d'erreur et un message au format standardisé
|
|
// GO-014: Harmonisation format erreurs HTTP selon ORIGIN_API_SPECIFICATION
|
|
func RespondWithError(c *gin.Context, code int, message string, details ...errors.ErrorDetail) {
|
|
statusCode := mapErrorCodeToHTTPStatus(errors.ErrorCode(code))
|
|
|
|
errorData := struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Details []errors.ErrorDetail `json:"details,omitempty"`
|
|
RequestID string `json:"request_id,omitempty"`
|
|
Timestamp string `json:"timestamp"`
|
|
}{
|
|
Code: code,
|
|
Message: message,
|
|
Details: details,
|
|
RequestID: c.GetString("request_id"),
|
|
Timestamp: time.Now().UTC().Format(time.RFC3339),
|
|
}
|
|
|
|
c.JSON(statusCode, APIResponse{
|
|
Success: false,
|
|
Data: nil,
|
|
Error: errorData,
|
|
})
|
|
}
|
|
|
|
// mapErrorCodeToHTTPStatus mappe les codes d'erreur ORIGIN vers les codes HTTP
|
|
// GO-014: Harmonisation format erreurs HTTP selon ORIGIN_API_SPECIFICATION
|
|
func mapErrorCodeToHTTPStatus(code errors.ErrorCode) int {
|
|
// Authentication & Authorization (1000-1999)
|
|
if code >= 1000 && code < 2000 {
|
|
switch code {
|
|
case 1000, 1001, 1002, 1007, 1008: // Invalid credentials, token expired/invalid, 2FA
|
|
return http.StatusUnauthorized
|
|
case 1003, 1004, 1005, 1006: // Insufficient permissions, account issues
|
|
return http.StatusForbidden
|
|
default:
|
|
return http.StatusUnauthorized
|
|
}
|
|
}
|
|
|
|
// Validation Errors (2000-2999)
|
|
if code >= 2000 && code < 3000 {
|
|
return http.StatusBadRequest
|
|
}
|
|
|
|
// Resource Errors (3000-3999)
|
|
if code >= 3000 && code < 4000 {
|
|
switch code {
|
|
case 3000, 3003: // Not found, deleted
|
|
return http.StatusNotFound
|
|
case 3001, 3002: // Already exists, conflict
|
|
return http.StatusConflict
|
|
case 3004: // Locked
|
|
return http.StatusLocked
|
|
case 3005: // Quota exceeded
|
|
return http.StatusForbidden
|
|
default:
|
|
return http.StatusNotFound
|
|
}
|
|
}
|
|
|
|
// Business Logic Errors (4000-4999)
|
|
if code >= 4000 && code < 5000 {
|
|
return http.StatusUnprocessableEntity
|
|
}
|
|
|
|
// Rate Limiting (5000-5099)
|
|
if code >= 5000 && code < 5100 {
|
|
return http.StatusTooManyRequests
|
|
}
|
|
|
|
// External Services (6000-6999)
|
|
if code >= 6000 && code < 7000 {
|
|
return http.StatusBadGateway
|
|
}
|
|
|
|
// Internal Errors (9000-9999)
|
|
if code >= 9000 && code < 10000 {
|
|
return http.StatusInternalServerError
|
|
}
|
|
|
|
// Default
|
|
return http.StatusInternalServerError
|
|
}
|