veza/veza-backend-api/internal/response/response.go

145 lines
4.3 KiB
Go
Raw Normal View History

2025-12-03 19:29:37 +00:00
package response
import (
"net/http"
2025-12-16 16:23:49 +00:00
"time"
apperrors "veza-backend-api/internal/errors"
2025-12-03 19:29:37 +00:00
"github.com/gin-gonic/gin"
)
// APIResponse is the unified response envelope
type APIResponse struct {
Success bool `json:"success"`
Data interface{} `json:"data,omitempty"`
Error interface{} `json:"error,omitempty"`
}
2025-12-03 19:29:37 +00:00
// Success sends a successful JSON response
func Success(c *gin.Context, data interface{}, message ...string) {
response := gin.H{
"success": true,
"data": data,
}
if len(message) > 0 {
response["message"] = message[0]
}
c.JSON(http.StatusOK, response)
}
// Created sends a 201 Created response
func Created(c *gin.Context, data interface{}, message ...string) {
response := gin.H{
"success": true,
"data": data,
}
if len(message) > 0 {
response["message"] = message[0]
}
c.JSON(http.StatusCreated, response)
}
// BadRequest sends a 400 Bad Request response
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-03 19:29:37 +00:00
func BadRequest(c *gin.Context, message string) {
2025-12-16 16:23:49 +00:00
Error(c, http.StatusBadRequest, message)
2025-12-03 19:29:37 +00:00
}
// Unauthorized sends a 401 Unauthorized response
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-03 19:29:37 +00:00
func Unauthorized(c *gin.Context, message string) {
2025-12-16 16:23:49 +00:00
Error(c, http.StatusUnauthorized, message)
2025-12-03 19:29:37 +00:00
}
// Forbidden sends a 403 Forbidden response
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-03 19:29:37 +00:00
func Forbidden(c *gin.Context, message string) {
2025-12-16 16:23:49 +00:00
Error(c, http.StatusForbidden, message)
2025-12-03 19:29:37 +00:00
}
// NotFound sends a 404 Not Found response
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-03 19:29:37 +00:00
func NotFound(c *gin.Context, message string) {
2025-12-16 16:23:49 +00:00
Error(c, http.StatusNotFound, message)
2025-12-03 19:29:37 +00:00
}
// InternalServerError sends a 500 Internal Server Error response
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-03 19:29:37 +00:00
func InternalServerError(c *gin.Context, message string) {
2025-12-16 16:23:49 +00:00
Error(c, http.StatusInternalServerError, message)
2025-12-03 19:29:37 +00:00
}
// Error sends a custom error response with specified status code
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-03 19:29:37 +00:00
func Error(c *gin.Context, status int, message string) {
2025-12-16 16:23:49 +00:00
// Convertir status HTTP vers ErrorCode
var errorCode apperrors.ErrorCode
switch status {
case http.StatusBadRequest:
errorCode = apperrors.ErrCodeValidation
case http.StatusUnauthorized:
errorCode = apperrors.ErrCodeInvalidCredentials
case http.StatusForbidden:
errorCode = apperrors.ErrCodeForbidden
case http.StatusNotFound:
errorCode = apperrors.ErrCodeNotFound
case http.StatusConflict:
errorCode = apperrors.ErrCodeConflict
case http.StatusInternalServerError:
errorCode = apperrors.ErrCodeInternal
default:
errorCode = apperrors.ErrCodeInternal
}
appErr := apperrors.New(errorCode, message)
RespondWithAppError(c, status, appErr)
}
// RespondWithAppError répond avec une AppError au format standardisé
// P0: Helper pour utiliser AppError depuis le package response
func RespondWithAppError(c *gin.Context, statusCode int, appErr *apperrors.AppError) {
errorData := struct {
Code int `json:"code"`
Message string `json:"message"`
Details []apperrors.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,
}
// Utiliser la structure APIResponse standardisée
type APIResponse struct {
Success bool `json:"success"`
Data interface{} `json:"data,omitempty"`
Error interface{} `json:"error,omitempty"`
}
c.JSON(statusCode, APIResponse{
Success: false,
Data: nil,
Error: errorData,
2025-12-03 19:29:37 +00:00
})
}
2025-12-13 02:34:34 +00:00
// ValidationError sends a 400 Bad Request response with detailed validation errors
2025-12-16 16:23:49 +00:00
// P0: Migré vers format AppError standardisé
2025-12-13 02:34:34 +00:00
func ValidationError(c *gin.Context, message string, details map[string]string) {
2025-12-16 16:23:49 +00:00
errorDetails := make([]apperrors.ErrorDetail, 0, len(details))
for field, msg := range details {
errorDetails = append(errorDetails, apperrors.ErrorDetail{
Field: field,
Message: msg,
})
}
appErr := apperrors.NewValidationError(message, errorDetails...)
RespondWithAppError(c, http.StatusBadRequest, appErr)
2025-12-13 02:34:34 +00:00
}