Skip to content

REST API Error Handling - Problem Details Response

El Problema

Cada programador o equipo están tratando de definir su propia filosofía de respuesta a errores. Pero la estructura común que define un "buen código de error" consiste en tres criterios básicos para que este sea realmente útil:

  • HTTP Status Code.
  • Referencia interna a la documentación.
  • Mensajes legibles que resuman el contexto, la causa y la solución general del error en cuestión.

RFC 7807 al rescate

Este documento define un "detalle del problema" como una forma de llevar detalles de errores mas legibles en una respuesta HTTP para evitar la necesidad de definir nuevos formatos de respuesta de error para las API HTTP.

Al proporcionar mensajes más específicos con una respuesta de error, los clientes de la API pueden reaccionar a los errores de manera más efectiva y eventualmente hace que la API sean mucho más confiables desde la perspectiva de prueba REST API y los clientes también. En el siguiente link se puede ver la especificacion RFC7807

Implementacion

Al incorporar Infra.Web.Problems a un proyecto, el mismo cuenta con metodos extendidos que nos ayudaran a retornar un ProblemDetail desde cualquier modulo de Carter.

Retornando un Problema

Get("/api/some", async (req, res) => {

  var problem = new ProblemDetails
  {
    ProblemType = new Uri("http://example.org"), 
    Title = "Houston we have a problem",
    StatusCode = HttpStatusCode.BadGateway,
   };

   await res.AsProblem(problem);
});
HTTP/1.1 502 Bad Gateway
Content-Type: application/problem+json
{
  "type": "http://example.org",
  "title": "Houston we have a problem",
  "status": 502,
}

Retornando errores de validación

Get("/api/someerror", async (req, res) => {

    var result = await req.BindAndValidate<GetRequest>();
    if (!result.ValidationResult.IsValid)
    {
      await res.AsProblem(result.ValidationResult,
             title: "Errores de validacion",
            detail: "Verificar Errors para mas detalle");
      return;
    }
    await res.WriteAsync("Exito");
});
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
{
  "errors": [
    {
      "field": "Limit",
      "messages": [
        "El valor limite debe ser mayor a cero.",
        "Debe estar en un rango entre 10 y 20"
      ]
    }
  ],
  "type": "about:blank",
  "title": "Errores de validacion",
  "status": 422,
  "detail": "Verificar Errors para mas detalle"
}

Totalmente Extensible

Se pueden crea nuevos problemas heredando de la clase ProblemDetail y agregando las propiedades que se necesiten para cada problema especifico. A continuación se puede observar la clase ValidationProblemDetails la cual es utilizada por la misma librería para retornar los errores de validación.

public class ValidationProblemDetails : ProblemDetails
{
  public IEnumerable<object> Errors { get; set; }
}