Al desarrollar una API HTTP, el manejo de errores suele ser una parte engorrosa. A medida que aumenta la cantidad de APIs y la lógica interna se vuelve más compleja, surgen dificultades en tres aspectos.
- Devolver códigos de error adecuados: en el caso de desarrolladores con poca experiencia, es difícil usar códigos de estado HTTP consistentes dentro de lógica compleja.
- Escribir una gran cantidad de logs de resultados: registrar logs en todos los puntos de salida esperados cuando ocurre un error aumenta la cantidad de código y complica su gestión.
- Enviar mensajes de error claros: simplemente pasar un mensaje de error al cliente no basta para comprender y manejar el error con claridad.
Mejorar la devolución de códigos de error adecuados
Para resolver el problema de la consistencia en el uso de códigos de error, se propone implementar una interfaz o estructura HttpError que incluya StatusCode y Message.
- Solución:
- Definir el tipo
HttpError: encapsula el código de estado HTTP y el mensaje. - Proveer funciones helper: usar funciones helper que devuelvan códigos de error específicos, como
httperror.BadRequest("wrong format"), para crear fácilmente objetos de error.
- Definir el tipo
- Ventajas:
- Aprovechar el autocompletado del IDE para ingresar de forma cómoda y segura códigos y mensajes de error.
- Reducir la posibilidad de errores frente a escribir códigos numéricos manualmente.
- Disminuir la molestia de tener que revisar uno por uno los documentos de diseño preparados de antemano.
Centralización del registro de logs
Para reducir la escritura repetitiva de logs y gestionar la lógica de manejo de errores en un solo lugar, se presenta un método para envolver el handler HTTP.
- Solución:
- Implementar un router personalizado (
chiwrap.Router): incluye internamente un router existente comochi.Routery agrega lógica de manejo de errores. - Envolver handlers: métodos como
Getdel router personalizado recibenHandlerFunc, lo ejecutan internamente y, si ocurre un error, lo pasan a la lógica centralizada de manejo. - Función callback de error: al crear
NewRouter, recibe una funciónerrCallbacky, cuando ocurre un error, llama ese callback para registrar logs de forma centralizada o realizar procesamiento adicional.
- Implementar un router personalizado (
- Ventajas:
- Cuando ocurre un error en la lógica de la API, se devuelve automáticamente en la respuesta el código y mensaje de error adecuados.
- Es fácil gestionar los logs registrando funciones callback para que cada servicio escriba los logs apropiados.
- Reduce la duplicación de código y mejora la mantenibilidad.
Envío de mensajes de error claros (uso de RFC7807)
Se propone un método para enviar mensajes de error estructurados usando el estándar RFC7807, de modo que el cliente pueda entender y manejar los errores con mayor claridad.
- Elementos principales de RFC7807:
type: URI que identifica el tipo de error (ej.:https://example.com/errors/validation).title: explicación breve del error en una sola línea.status: igual al código de estado HTTP.detail: descripción detallada del error legible para humanos.instance: URI específica donde ocurrió el error (ej.:/api/users/abc).extensions: objeto JSON que contiene información adicional (ej.:invalid_field,expected_format).
- Implementación:
-
Crear una estructura
RFC7807Errore incluir sus elementos principales. -
Crear fácilmente objetos de error estructurados mediante el patrón de method chaining (
WithType(),WithInstance(),WithExtension()). -
Convertir
RFC7807ErroraHttpErrormediante el métodoToHttpError()para poder integrarlo con el router centralizado. -
El cliente puede identificar con claridad el tipo, la causa y la ubicación del error.
-
Se mejora la consistencia y utilidad de las respuestas de la API, aumentando la eficiencia del desarrollo del cliente.
-
5 comentarios
Gracias por el buen artículo.
¡Gracias por el buen artículo!
Como referencia, en Spring existe una implementación en la librería
spirng-web, enorg.springframework.http.ProblemDetail.¡Gracias por la buena introducción!
Por lo que vi, fue reemplazado por el RFC 9457.
https://datatracker.ietf.org/doc/html/rfc9457
(documento 7807 anterior: https://datatracker.ietf.org/doc/html/rfc7807)
Principales diferencias entre RFC 7807 y RFC 9457
errorspointerSe recomienda aplicar RFC 9457 en proyectos nuevos desde julio de 2023
Parece que se recomienda configurar el campo
typecomo un URI que se pueda desreferenciar.En los servicios internos, probablemente no haya problema en reemplazarlo por un enlace a la documentación de Swagger UI.