Implementa el contrato de errores de TicketFlow. Sin solutions.md hasta entregar.
Ejercicio 1 — La taxonomía
- Enumera las excepciones de dominio de TicketFlow con su status: asiento ocupado (409), reserva expirada (410), evento agotado (409), pago rechazado (402 o 409 — decide y justifica), saldo de tarjeta regalo insuficiente (409 o 422 — decide), no autenticado (401, la maneja DRF).
- Para cada una escribe el problem+json completo (type, title, status, detail) tal como lo vería el cliente del front.
Ejercicio 2 — El handler
- Implementa
problem_handlerconto_problem()yproblem_response(), conéctalo en settings y haz que los errores de validación de DRF salgan como problem+json (status 400, type.../validation-error, yerrorscon el dict de campo → mensajes). - Escribe el test de contrato: POST a reserva con body inválido → 400 con Content-Type
application/problem+jsonytypeque termina envalidation-error. - Haz que una vista ANTERIOR (la que aún devuelve
Response({"error":...})) se migre: borra su try/except, lanza la excepción de dominio, y verifica con el test que la respuesta no cambió (el test es la red de la 28).
Ejercicio 3 — Extra accionable
- Añade
extraaSeatUnavailable(conflicting_seats)y aReservationExpired(retry_after)— en este caso también el headerRetry-After. ¿Dónde lo inyecta el handler? - Test: reserva expirada → 410 con header
Retry-After: 30y body conretry_after: 30.
Ejercicio 4 — El 500 sano
- Fuerza un 500 (una vista que lanza
ZeroDivisionErroren un endpoint de test). Verifica: body problem+json genérico SIN stack, log conlogger.exceptiony el trace_id presente. - Añade la métrica
http_5xx_total{path}(contador en memoria o Redis, la 46 la formaliza) incrementada en el handler. ¿Por qué en el handler y no en un middleware aparte? (pista: un solo lugar). - Decide y escribe: ¿un 429 (rate limit de la 23) debe loggearse con warning o es ruido? ¿Y un 401?
Ejercicio 5 — El cliente que programa contra el contrato
- Escribe un test que consuma la API con un cliente HTTP fingido y aplique TODAS las reglas: cada error 4xx/5xx tiene
typeURI absoluto,titleno vacío,statusque coincide con el HTTP,trace_idpresente en 5xx. Una sola funciónassert_problem(response). - Pégala en 3 tests distintos (validación, dominio, 500). ¿Cuántas líneas te ahorró frente a escribir las assertions a mano en cada uno?
Entrega
Pega la taxonomía, el handler completo, el test de contrato y el test del 500. Después: Lección 27 — Configuración 12-factor.