veza/veza-backend-api/internal/handlers/bitrate_handler.go
senke b619e5a982 api-contracts: update backend handlers to use wrapped format
- Updated system_metrics.go to use RespondSuccess() helper
- Updated bitrate_handler.go success responses to use wrapped format
- Updated frontend_log_handler.go to use RespondSuccess() helper
- Updated csrf.go to use RespondSuccess() and RespondWithError() helpers
- Updated audit.go: all 30+ error and success responses now use wrapped format helpers
- Updated comment_handler.go error responses to use RespondWithError()
- Updated system_metrics_test.go to expect wrapped format {success, data}
- All handlers now consistently use wrapped format helpers
- Build and tests pass successfully
- Action 1.3.2.1 complete - backend handlers standardized to wrapped format
2026-01-15 17:32:02 +01:00

144 lines
5.1 KiB
Go

package handlers
import (
"context"
"errors"
"net/http"
apperrors "veza-backend-api/internal/errors"
"veza-backend-api/internal/services"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
)
// BitrateAdaptationServiceInterface defines methods needed for bitrate handler
type BitrateAdaptationServiceInterface interface {
AdaptBitrate(ctx context.Context, trackID, userID uuid.UUID, currentBitrate int, bandwidth int64, bufferLevel float64) (int, error)
GetAnalytics(ctx context.Context, trackID uuid.UUID) (*services.BitrateAnalytics, error)
}
// BitrateHandler gère les requêtes pour l'adaptation de bitrate
// T0349: Create Bitrate Adaptation Endpoint
type BitrateHandler struct {
adaptationService BitrateAdaptationServiceInterface
commonHandler *CommonHandler
}
// NewBitrateHandler crée un nouveau handler de bitrate
func NewBitrateHandler(adaptationService *services.BitrateAdaptationService, logger *zap.Logger) *BitrateHandler {
return &BitrateHandler{
adaptationService: adaptationService,
commonHandler: NewCommonHandler(logger),
}
}
// NewBitrateHandlerWithInterface creates a new bitrate handler with interface (for testing)
func NewBitrateHandlerWithInterface(adaptationService BitrateAdaptationServiceInterface, logger *zap.Logger) *BitrateHandler {
return &BitrateHandler{
adaptationService: adaptationService,
commonHandler: NewCommonHandler(logger),
}
}
// AdaptBitrateRequest représente la requête pour adapter le bitrate
type AdaptBitrateRequest struct {
CurrentBitrate int `json:"current_bitrate" binding:"required" validate:"required"`
Bandwidth int64 `json:"bandwidth" binding:"required" validate:"required"`
BufferLevel float64 `json:"buffer_level" binding:"required" validate:"required"`
}
// AdaptBitrate gère la requête POST /api/v1/tracks/:id/bitrate/adapt
// Reçoit les métriques de streaming et retourne le bitrate recommandé
func (h *BitrateHandler) AdaptBitrate(c *gin.Context) {
// Récupérer l'ID de l'utilisateur depuis le contexte (défini par le middleware d'authentification)
userIDVal, exists := c.Get("user_id")
if !exists {
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
return
}
userID, ok := userIDVal.(uuid.UUID)
if !ok || userID == uuid.Nil {
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
return
}
// Récupérer l'ID du track depuis les paramètres de l'URL
trackIDStr := c.Param("id")
trackID, err := uuid.Parse(trackIDStr)
if err != nil {
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid track id"))
return
}
// Valider et parser le body de la requête
var req AdaptBitrateRequest
if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
return
}
// Appeler le service d'adaptation de bitrate
newBitrate, err := h.adaptationService.AdaptBitrate(
c.Request.Context(),
trackID,
userID,
req.CurrentBitrate,
req.Bandwidth,
req.BufferLevel,
)
if err != nil {
// Le service retourne des erreurs de validation avec des messages spécifiques
// On peut distinguer les erreurs de validation des erreurs internes
if errors.Is(err, services.ErrInvalidTrackID) ||
errors.Is(err, services.ErrInvalidUserID) ||
errors.Is(err, services.ErrInvalidBitrate) ||
errors.Is(err, services.ErrInvalidBufferLevel) {
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, err.Error()))
return
}
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeInternal, err.Error()))
return
}
// Retourner le bitrate recommandé
// Action 1.3.2.1: Use wrapped format helper
RespondSuccess(c, http.StatusOK, gin.H{"recommended_bitrate": newBitrate})
}
// GetAnalytics gère la requête GET /api/v1/tracks/:id/bitrate/analytics
// Retourne les statistiques d'adaptation de bitrate pour un track
// T0354: Create Bitrate Adaptation Analytics Endpoint
func (h *BitrateHandler) GetAnalytics(c *gin.Context) {
// Récupérer l'ID du track depuis les paramètres de l'URL
trackIDStr := c.Param("id")
trackID, err := uuid.Parse(trackIDStr)
if err != nil {
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid track id"))
return
}
// Récupérer les analytics depuis le service
analytics, err := h.adaptationService.GetAnalytics(c.Request.Context(), trackID)
if err != nil {
if errors.Is(err, services.ErrInvalidTrackID) {
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid track id"))
return
}
// MOD-P2-003: Utiliser AppError au lieu de gin.H
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeInternal, err.Error()))
return
}
// Retourner les analytics
// Action 1.3.2.1: Use wrapped format helper
RespondSuccess(c, http.StatusOK, gin.H{"analytics": analytics})
}