veza/veza-backend-api/P1_RES_001_ERROR_PATTERN_MIGRATION_REPORT.md

286 lines
9.2 KiB
Markdown
Raw Normal View History

2025-12-13 02:34:34 +00:00
# ✅ P1-RES-001 — STANDARDISATION PATTERNS DE RÉPONSE D'ERREUR
**Date**: 2025-12-12
**Objectif**: Standardiser les patterns de réponse d'erreur en migrant TrackHandler vers `RespondWithAppError`
---
## 📋 RÉSUMÉ
**Pattern cible identifié** : `RespondWithAppError` (conforme ORIGIN_API_SPECIFICATION)
**Helper créé** : `respondWithError()` pour faciliter la migration
**Endpoints critiques migrés** : UploadTrack, GetUploadStatus, UpdateTrack, DeleteTrack
**Tests ajoutés** : Vérification de la forme des erreurs (structure JSON)
**Compilation réussie** : Aucune erreur de compilation
---
## 📁 FICHIERS MODIFIÉS
### 1. `internal/core/track/handler.go`
-**Imports ajoutés** : `apperrors`, `handlers` pour utiliser `RespondWithAppError` et `RespondSuccess`
-**Helper `respondWithError()` créé** (lignes 113-127) : Convertit HTTP status → ErrorCode → RespondWithAppError
-**Helper `getUserID()` mis à jour** : Utilise maintenant `RespondWithAppError` au lieu de `response.Unauthorized`
-**Endpoints critiques migrés** :
1. `UploadTrack` : `response.BadRequest``h.respondWithError()`, `response.Created``handlers.RespondSuccess()`
2. `GetUploadStatus` : `response.BadRequest`, `response.InternalServerError`, `response.Success` → format standardisé
3. `UpdateTrack` : `response.BadRequest`, `response.NotFound`, `response.Forbidden`, `response.InternalServerError`, `response.Success` → format standardisé
4. `DeleteTrack` : `response.BadRequest`, `response.NotFound`, `response.Forbidden`, `response.InternalServerError`, `response.Success` → format standardisé
### 2. `internal/core/track/handler_error_format_test.go` (nouveau)
-`TestTrackHandler_ErrorResponseFormat` : Teste la structure JSON des erreurs (code, message, timestamp)
-`TestTrackHandler_SuccessResponseFormat` : Teste la structure JSON des réponses de succès
---
## 🔍 IMPLÉMENTATION
### Pattern cible : `RespondWithAppError`
**Format standardisé** :
```json
{
"success": false,
"error": {
"code": 2000,
"message": "invalid track id",
"timestamp": "2025-12-12T19:00:00Z",
"request_id": "...",
"details": []
}
}
```
### Helper créé
```go
// respondWithError est un helper pour migrer vers RespondWithAppError
// MOD-P1-RES-001: Helper pour standardiser les réponses d'erreur
func (h *TrackHandler) respondWithError(c *gin.Context, httpStatus int, message string) {
var errCode apperrors.ErrorCode
switch httpStatus {
case http.StatusBadRequest:
errCode = apperrors.ErrCodeValidation
case http.StatusUnauthorized:
errCode = apperrors.ErrCodeUnauthorized
case http.StatusForbidden:
errCode = apperrors.ErrCodeForbidden
case http.StatusNotFound:
errCode = apperrors.ErrCodeNotFound
case http.StatusInternalServerError:
errCode = apperrors.ErrCodeInternal
default:
errCode = apperrors.ErrCodeInternal
}
handlers.RespondWithAppError(c, apperrors.New(errCode, message))
}
```
### Pattern de remplacement
**Avant** (format simple) :
```go
response.BadRequest(c, "invalid track id")
// → {"success": false, "error": "invalid track id"}
```
**Après** (format structuré) :
```go
h.respondWithError(c, http.StatusBadRequest, "invalid track id")
// → {"success": false, "error": {"code": 2000, "message": "invalid track id", "timestamp": "...", ...}}
```
---
## 📊 MATRICE AVANT/APRÈS
| Endpoint | Méthode | Avant (Pattern) | Après (Pattern) | Status HTTP | Format erreur |
|----------|---------|----------------|-----------------|------------|---------------|
| `POST /tracks` | UploadTrack | `response.BadRequest()` | `h.respondWithError()` | 400 | ✅ Structuré |
| `POST /tracks` | UploadTrack | `response.Created()` | `handlers.RespondSuccess()` | 201 | ✅ Standardisé |
| `GET /tracks/:id/progress` | GetUploadStatus | `response.BadRequest()` | `h.respondWithError()` | 400 | ✅ Structuré |
| `GET /tracks/:id/progress` | GetUploadStatus | `response.Success()` | `handlers.RespondSuccess()` | 200 | ✅ Standardisé |
| `PUT /tracks/:id` | UpdateTrack | `response.BadRequest()` | `h.respondWithError()` | 400 | ✅ Structuré |
| `PUT /tracks/:id` | UpdateTrack | `response.NotFound()` | `h.respondWithError()` | 404 | ✅ Structuré |
| `PUT /tracks/:id` | UpdateTrack | `response.Forbidden()` | `h.respondWithError()` | 403 | ✅ Structuré |
| `PUT /tracks/:id` | UpdateTrack | `response.Success()` | `handlers.RespondSuccess()` | 200 | ✅ Standardisé |
| `DELETE /tracks/:id` | DeleteTrack | `response.BadRequest()` | `h.respondWithError()` | 400 | ✅ Structuré |
| `DELETE /tracks/:id` | DeleteTrack | `response.NotFound()` | `h.respondWithError()` | 404 | ✅ Structuré |
| `DELETE /tracks/:id` | DeleteTrack | `response.Forbidden()` | `h.respondWithError()` | 403 | ✅ Structuré |
| `DELETE /tracks/:id` | DeleteTrack | `response.Success()` | `handlers.RespondSuccess()` | 200 | ✅ Standardisé |
---
## 🧪 PREUVES (TESTS)
### Tests unitaires
```bash
go test ./internal/core/track -run TestTrackHandler_ErrorResponseFormat -v -count=1
```
**Résultat** : ✅ **Tests passent** (vérification de la structure JSON)
#### Test 1 : Format des erreurs
```go
TestTrackHandler_ErrorResponseFormat
```
- ✅ Vérifie que les erreurs suivent le format `RespondWithAppError`
- ✅ Vérifie la présence des champs : `code`, `message`, `timestamp`
- ✅ Vérifie que `code` est un nombre positif
- ✅ Vérifie que `message` est une string non vide
- ✅ Vérifie que `timestamp` est au format RFC3339
#### Test 2 : Format des réponses de succès
```go
TestTrackHandler_SuccessResponseFormat
```
- ✅ Vérifie que les réponses de succès suivent le format `RespondSuccess`
- ✅ Vérifie la présence des champs : `success`, `data`
- ✅ Vérifie que `success` est `true`
### Tests complets
```bash
go test ./internal/core/track -v -count=1
```
**Résultat** : ✅ **Tous les tests passent**
---
## 📊 COMPARAISON DES PATTERNS
### Pattern `internal/response` (ancien)
**Format** :
```json
{
"success": false,
"error": "invalid track id"
}
```
**Avantages** :
- Simple et direct
- Facile à utiliser
**Inconvénients** :
- Pas de code d'erreur standardisé
- Pas de timestamp
- Pas de détails structurés
- Incohérent avec ProfileHandler
### Pattern `RespondWithAppError` (nouveau)
**Format** :
```json
{
"success": false,
"error": {
"code": 2000,
"message": "invalid track id",
"timestamp": "2025-12-12T19:00:00Z",
"request_id": "...",
"details": []
}
}
```
**Avantages** :
- ✅ Format structuré et standardisé
- ✅ Code d'erreur pour traitement programmatique
- ✅ Timestamp pour debugging
- ✅ Request ID pour traçabilité
- ✅ Détails pour erreurs de validation
- ✅ Cohérent avec ProfileHandler et autres handlers
- ✅ Conforme à ORIGIN_API_SPECIFICATION
---
## ✅ VALIDATION
### Compilation
```bash
go build ./internal/core/track/...
```
**Résultat** : ✅ **Compilation réussie**
### Tests unitaires
```bash
go test ./internal/core/track -run TestTrackHandler_ErrorResponseFormat -v
```
**Résultat** : ✅ **Tests passent**
### Tests complets
```bash
go test ./internal/core/track -v -count=1
```
**Résultat** : ✅ **Tous les tests passent**
### Vérification cohérence
Les endpoints suivants utilisent maintenant le **même format** que ProfileHandler :
-`POST /tracks` (UploadTrack)
-`GET /tracks/:id/progress` (GetUploadStatus)
-`PUT /tracks/:id` (UpdateTrack)
-`DELETE /tracks/:id` (DeleteTrack)
---
## 🎯 OBJECTIFS ATTEINTS
-**Pattern cible identifié** : `RespondWithAppError` (conforme ORIGIN_API_SPECIFICATION)
-**Endpoints critiques migrés** : 4 endpoints les plus exposés
-**Helper créé** : `respondWithError()` pour faciliter la migration
-**Tests ajoutés** : Vérification de la structure JSON des erreurs
-**Cohérence améliorée** : TrackHandler et ProfileHandler utilisent maintenant le même format
---
## 📋 COMMANDES DE VALIDATION
### Compilation
```bash
go build ./internal/core/track/...
```
### Tests spécifiques
```bash
go test ./internal/core/track -run TestTrackHandler_ErrorResponseFormat -v -count=1
go test ./internal/core/track -run TestTrackHandler_SuccessResponseFormat -v -count=1
```
### Tests complets
```bash
go test ./internal/core/track -v -count=1
```
---
## 📝 ENDPOINTS DÉSORMAIS COHÉRENTS
Les endpoints suivants utilisent maintenant le **format standardisé** `RespondWithAppError` / `RespondSuccess` :
1.**`POST /tracks`** (UploadTrack) - Endpoint très exposé
2.**`GET /tracks/:id/progress`** (GetUploadStatus) - Utilisé fréquemment
3.**`PUT /tracks/:id`** (UpdateTrack) - Modification critique
4.**`DELETE /tracks/:id`** (DeleteTrack) - Suppression critique
Ces endpoints sont maintenant **cohérents** avec :
-`ProfileHandler` (GetProfile, UpdateProfile, etc.)
-`PlaylistHandler` (utilise déjà `RespondWithAppError`)
-`AuthHandler` (utilise déjà `RespondWithAppError`)
---
**Statut final** : ✅ **P1-RES-001 IMPLÉMENTÉ ET VALIDÉ**
**Note** : La migration complète de tous les endpoints TrackHandler vers `RespondWithAppError` peut être effectuée progressivement. Les 4 endpoints critiques ont été migrés pour supprimer l'incohérence observable côté clients.