22 puntos por lemonmint 2025-06-02 | 5 comentarios | Compartir por WhatsApp

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.
  • 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 como chi.Router y agrega lógica de manejo de errores.
    • Envolver handlers: métodos como Get del router personalizado reciben HandlerFunc, 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ón errCallback y, cuando ocurre un error, llama ese callback para registrar logs de forma centralizada o realizar procesamiento adicional.
  • 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 RFC7807Error e incluir sus elementos principales.

    • Crear fácilmente objetos de error estructurados mediante el patrón de method chaining (WithType(), WithInstance(), WithExtension()).

    • Convertir RFC7807Error a HttpError mediante el método ToHttpError() 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

 
aer0700 2025-06-02

Gracias por el buen artículo.

 
beoks 2025-06-02

¡Gracias por el buen artículo!
Como referencia, en Spring existe una implementación en la librería spirng-web, en org.springframework.http.ProblemDetail.

 
honglu 2025-06-02

¡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)

 
findnamo 2025-06-02

Principales diferencias entre RFC 7807 y RFC 9457

  • Gestión de tipos de problema: 7807 solo permite URI personalizadas; 9457 introduce un registro compartido de IANA
  • Manejo de múltiples errores: 7807 recomienda usar el código de estado HTTP 207; 9457 agrupa errores relacionados dentro de un solo tipo de problema usando un arreglo errors
  • Campos de extensión: 7807 permite agregar campos arbitrarios; 9457 asocia explícitamente los campos esperados para cada tipo de problema
  • Recomendaciones de seguridad: 7807 no las incluye; 9457 agrega lineamientos explícitos para prevenir vulnerabilidades de seguridad
  • JSON Pointer: 7807 no lo soporta; 9457 ofrece soporte oficial para el campo pointer

Se recomienda aplicar RFC 9457 en proyectos nuevos desde julio de 2023

 
honglu 2025-06-02

Parece que se recomienda configurar el campo type como 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.