Tema representativo de entrevista

Entrevista de backend: diseñar un contrato unificado de errores de API HTTP con RFC 9457

BackendIntermedio
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Varios clientes llaman a una API HTTP cuyos formatos de error son inconsistentes. Diseñe una respuesta de error unificada según RFC 9457 que cubra tipos, códigos de estado, campos de validación, sugerencias de reintento, localización e información confidencial.

Planteamiento y alcance

Esta pregunta de backend evalúa los contratos de API y los límites de fallas. El objetivo no es encapsular cada excepción en un solo objeto JSON, sino permitir que los clientes tomen una acción estable mientras los logs, el rastreo, los permisos y el texto orientado al usuario permanecen como capas separadas.

Qué evalúa el entrevistador

  • Si comprende la relación entre application/problem+json y los códigos de estado HTTP.
  • Si la validación, autenticación, autorización, conflictos, límites de tasa, fallas temporales y errores desconocidos están diferenciados.
  • Si diseña errores a nivel de campo, instancias rastreables y miembros de extensión controlados.
  • Si evita exponer trazas de pila (stacks), IDs internos, datos personales y excepciones no depuradas y no confiables.

Preguntas aclaratorias para hacer primero

Confirme si los clientes necesitan tomar decisiones automáticas por máquina o solo texto para mostrar, si existen localización, validación por lotes y trabajos asíncronos, si los tipos se comparten entre servicios, qué estados admiten reintentos y qué registran en logs, muestran y usan para la correlación de solicitudes la puerta de enlace (gateway), el servicio y el cliente.

Estructura de respuesta de 30 segundos

Utilice application/problem+json con type, title, status, detail y instance como una base estable. Agregue extensiones controladas para códigos, rutas de campo, tiempo de reintento y versión de documentación. El estado HTTP transmite la semántica general y type transmite una categoría programable; las causas internas permanecen en los logs mientras que la respuesta contiene información segura y procesable.

Respuesta a profundidad

1. Establecer los límites de estado y tipo

Utilice 400 para errores de sintaxis o de solicitud general, 401 para autenticación faltante, 403 para una solicitud reconocida pero no permitida, 404 para un recurso faltante, 409 para un conflicto con el estado actual, 429 para limitación de tasa (rate limiting) y 5xx para fallas del servidor o de dependencias. Haga que type sea un URI estable y documentado; los clientes no deberían analizar texto volátil de title o detail.

2. Diseñar los campos de Problem Details

type clasifica el problema, title es un resumen legible por humanos estable, status refleja la respuesta, detail explica esta solicitud y instance identifica esta ocurrencia. Las extensiones pueden incluir un código, ruta de campo, nombre de parámetro, tiempo de reintento o versión de documentación, con vocabulario y longitud delimitados. La validación por lotes puede devolver una matriz donde cada elemento apunta a una ubicación de entrada.

3. Manejar validación, conflictos y reintentos

Las fallas de validación deben indicar a los clientes cómo corregir un campo y no deben solicitar un reintento. Un conflicto necesita una relectura o una acción de negocio diferente. Un 429 o una falla temporal de dependencia puede incluir Retry-After, pero los clientes aún necesitan retroceso (backoff) y un límite de intentos. Haga que la posibilidad de reintento sea explícita en lugar de pedir a los clientes que la deduzcan de un mar de respuestas 200.

4. Proteger los límites de seguridad y privacidad

Nunca incluya trazas de pila (stacks), SQL, claves, nombres de host internos, detalles entre inquilinos (cross-tenant) o registros personales completos. Detail debe indicar únicamente un hecho procesable; instance debe ser una referencia impredecible o controlada. Correlacione la excepción sin procesar en los logs internos con un ID de solicitud. Evite fugas por enumeración de cuentas en errores de autenticación y filtre los errores de campo por permisos.

5. Evolucionar entre servicios y versiones

Coloque tipos, estados y extensiones compartidos en documentación versionada y pruebas de contrato; una puerta de enlace (gateway) no debe reescribir la semántica del servicio. Agregue campos de forma compatible y proporcione un período de migración para los tipos retirados. Los clientes deben recurrir al estado y al detalle seguro ante un tipo desconocido. Monitoree la distribución de tipos, el éxito de los reintentos, los puntos críticos de errores de campo y la trazabilidad de los ID de solicitud.

Ejemplo de una respuesta sólida

Declararía cada error como application/problem+json con un URI de tipo estable, title, status, detail e instance. Distinguiría 400/401/403/404/409/429 y 5xx mediante semántica HTTP; agregaría rutas de campo y un código seguro para validación, y Retry-After para limitación de tasa o una falla temporal de dependencia. Los clientes usan type para decidir si corregir, volver a consultar, aplicar backoff o contactar a soporte en lugar de analizar un detalle volátil. Los logs internos retienen trazas de pila, estado de dependencias e IDs de solicitud, mientras que las respuestas excluyen SQL, claves, datos de inquilinos y registros personales. Tipos versionados y pruebas de contrato protegen la evolución entre servicios; los tipos desconocidos recurren al código de estado. Monitoree tipos de errores, resultados de reintentos y puntos críticos de campos después del lanzamiento.

Errores comunes

  • Devolver 200 y una oración para cada error, dejando a los clientes incapaces de decidir programáticamente.
  • Hacer que los clientes dependan de la redacción literal de title o detail, de modo que una traducción rompa el comportamiento.
  • Etiquetar validaciones, conflictos, límites de tasa y fallas temporales como 500.
  • Devolver trazas de pila (stacks), SQL, nombres de host internos o datos completos de usuario en detail.
  • Exponer nombres de clases de excepción internas como tipos públicos y congelar detalles de implementación en el contrato.
  • No tener un mecanismo de respaldo (fallback) para tipos desconocidos o pruebas de contrato entre servicios.

Preguntas de seguimiento

¿Debe type ser una URL accesible?

Debe ser un URI estable y puede apuntar a documentación explicativa, pero los clientes no deberían requerir una solicitud de red para su manejo. Las propiedades importantes son la identidad semántica, el control de versiones y la orientación para la migración.

¿Debe localizarse detail?

Mantenga los campos de máquina y type estables y procese el texto de usuario en el cliente para su idioma y contexto. Si el servidor debe devolver detail, use plantillas seguras y negociación de idioma; nunca exponga una excepción interna no traducida.

¿Debería un gateway reescribir cada error?

Puede agregar IDs de solicitud, errores de tiempo de espera (timeout) y fallas a nivel de protocolo, pero debe preservar los tipos de negocio. La reescritura necesita reglas versionadas y observabilidad o los clientes verán una semántica que ya no coincide con la causa real.

¿Cómo maneja el éxito parcial en una solicitud por lotes?

Defina un resultado de lote con estado por elemento, ubicación de entrada y posibilidad de reintento, y especifique qué significa el estado HTTP general. Un detalle vago no puede expresar el éxito parcial, y los clientes no deben volver a enviar elementos que ya tuvieron éxito.

Fuentes públicas

Preguntas relacionadas