¿Deben usarse los códigos de estado HTTP para representar errores de lógica de negocios en un servidor?

20

Estoy en una encrucijada con un diseño de API para un cliente (JS en un navegador) para hablar con un servidor. Utilizamos HTTP 409 Conflict para representar el fallo de una acción debido a un bloqueo de seguridad vigente. El bloqueo de seguridad evita que los desarrolladores realicen cambios accidentalmente en los sistemas de producción de nuestros clientes. Se me ha encomendado el manejo de los 409 un poco más elegantes en el cliente para indicar por qué falló una llamada de API en particular.

Mi solución fue envolver los controladores de fallas de cualquiera de nuestras llamadas AJAX que mostrarán una notificación en el cliente cuando algo falla debido a 409: todo esto está bien y funciona bien junto con otros errores 4XX y 5XX que usan el mismo mecanismo.

Ha surgido un problema cuando uno de nuestros manejadores de ruta responde con 409 cuando se encuentra con un error de lógica de negocios: mi envoltorio AJAX informa que el bloqueo de seguridad está activado, mientras que el manejador de fallas existente del cliente informa qué (cree) que el problema se basa en el cuerpo de la respuesta Una solución simple sería cambiar la respuesta del manejador o el código de estado que usamos para representar el bloqueo de seguridad.

Lo que me lleva a mi encrucijada: ¿deberían los códigos de estado HTTP incluso usarse para representar errores de lógica de negocios? Esta pregunta aborda el mismo problema que estoy enfrentando pero no ganó mucha tracción. Como se sugiere en la respuesta vinculada, me estoy inclinando hacia el uso de HTTP 200 OK con un cuerpo apropiado para representar el fracaso dentro de la lógica empresarial.

¿Alguien tiene alguna opinión fuerte aquí? ¿Alguien puede convencerme de que esta es la forma incorrecta de representar el fracaso?

Joe Shanahan
fuente
3
Dudo en publicar mi simple opinión como respuesta. En resumen: generalmente evito usar códigos de estado HTTP para representar errores comerciales. Deben pertenecer solo al estado de la comunicación entre el cliente y el servidor. Sería un código de estado adecuado para devolver la validación o los errores de lógica de negocios 400 Bad Request. La razón de esta separación es porque los futuros sistemas, desarrolladores o lectores de documentos pueden confundirse por su desviación del estándar mundial.
Ivo Coumans
@IvoCoumans: por favor, haga de esta ^ una respuesta para que pueda votarla. 400 Bad Requestcomo código HTTP general parece mejor cubrir los errores de lógica de negocios como clase.
9000
Preferencia personal, pero tiendo a usar 400 Bad Requestcuando faltan datos o no se pueden leer / analizar. Es decir, los datos de la solicitud en sí son malos de alguna manera.
Kasey Speakman
Expanda lo que quiere decir con "error de lógica de negocios". Eso es extremadamente vago. ¿Se refiere a una entrada que no es válida de acuerdo con las verificaciones (correctas) de validación de datos, una entrada que podría ser válida en algún otro momento pero que no es válida en el estado actual o un error en la lógica de negocios donde se rechaza una entrada válida?
jpmc26
@ jpmc26 Estaba siendo intencionalmente vago, ya que era una pregunta general. Los servidores respondieron bien a la solicitud, pero decidieron que la consulta / afirmación no tenía sentido.
Joe Shanahan

Respuestas:

19

Kasey cubre el punto principal.

La idea clave en cualquier API web: está adaptando su dominio para que parezca un almacén de documentos. GET / PUT / POST / DELETE, etc., son todas formas de interactuar con el almacén de documentos.

Entonces, una forma de pensar acerca de qué códigos usar es comprender cómo es la operación análoga en un almacén de documentos y cómo se vería esta falla en ese análogo.

2xx es completamente inadecuado

La clase de código de estado 2xx (Correcto) indica que la solicitud del cliente se recibió, entendió y aceptó con éxito.

5xx tampoco es adecuado

La clase 5xx (Error de servidor) del código de estado indica que el servidor sabe que ha errado

En este caso, el servidor no cometió un error; es consciente de que no debes modificar ese recurso de esa manera en este momento.

Los errores de lógica empresarial (lo que significa que la invariante empresarial no permite la edición propuesta en este momento) son probablemente 409

El código de estado 409 (Conflicto) indica que la solicitud no se pudo completar debido a un conflicto con el estado actual del recurso de destino. Este código se usa en situaciones en las que el usuario podría resolver el conflicto y volver a enviar la solicitud. El servidor DEBE generar una carga útil que incluya suficiente información para que un usuario reconozca la fuente del conflicto.

Tenga en cuenta este último bit: la carga útil de la respuesta 409 debe comunicar información al consumidor sobre lo que salió mal, e idealmente incluye controles hipermedia que llevan al consumidor a los recursos que pueden ayudar a resolver el conflicto.

Mi solución fue envolver los controladores de fallas de cualquiera de nuestras llamadas AJAX que mostrarán una notificación en el cliente cuando algo falla debido a 409: todo esto está bien y funciona bien junto con otros errores 4XX y 5XX que usan el mismo mecanismo.

Y señalaría esto como el problema; su implementación en el cliente asumió que el código de estado era suficiente para definir el problema. En cambio, su código de cliente debería estar revisando la carga útil y actuando sobre la información disponible allí.

Así es, después de todo, cómo lo haría una tienda de documentos

409  Conflict

your proposed change has been declined because ${REASON}.  
The following resolution protocols are available: ${LINKS[@]})

El mismo enfoque con a 400 Bad Requesttambién sería aceptable; que aproximadamente "se traduce como" Hubo un problema con su solicitud. No podemos molestarnos en averiguar qué código de estado es el más adecuado, así que aquí tienes. Vea la carga útil para más detalles ".

Usaría 422. La entrada es válida, por lo que 400 no es el código de error correcto para usar

La especificación de WebDAV incluye esta recomendación

El código de estado 422 (entidad no procesable) significa que el servidor comprende el tipo de contenido de la entidad de solicitud (por lo tanto, un código de estado 415 (tipo de medio no admitido) es inapropiado) y la sintaxis de la entidad de solicitud es correcta (por lo tanto, un 400 (solicitud incorrecta) ) el código de estado es inapropiado) pero no pudo procesar las instrucciones contenidas. Por ejemplo, esta condición de error puede ocurrir si un cuerpo de solicitud XML contiene instrucciones XML bien formadas (es decir, sintácticamente correctas), pero semánticamente erróneas.

No creo que sea un buen partido (aunque estoy de acuerdo en que arroja algunas dudas 400como alternativa). Mi interpretación es que 422significa "has enviado la entidad equivocada" donde 409es "has enviado la entidad en el momento equivocado".

Dicho de otra manera, 422indica un problema con el mensaje de solicitud considerado de forma aislada, donde 409indica que el mensaje de solicitud entra en conflicto con el estado actual del recurso.

La discusión de Ben Nadal sobre 422 puede ser útil para considerar.

VoiceOfUnreason
fuente
55
" está adaptando su dominio para que parezca una tienda de documentos ". Me encantaría ver a la gente leer esto y comprender completamente todas las consecuencias e implicaciones antes de que decidan a favor (o en contra) de REST. De Verdad.
JensG
"Errores de lógica de negocios" me suena como "entrada inválida", que generalmente es 400, ya que no hay un código de error más específico. Si no es la entrada lo que no es válido, entonces el servidor tiene un error y 500 es apropiado. Su respuesta parece asumir demasiado sobre la naturaleza de un "error de lógica de negocios".
jpmc26
Usaría 422. La entrada es válida, por lo que 400 no es el código de error correcto para usar
Konrad
19

En mi experiencia, los códigos de error HTTP son insuficientes para representar errores comerciales. Sin embargo, son útiles para representar clases de errores.

Por lo tanto, mi recomendación sería usar códigos de error HTTP para categorías de errores, pero elegir un error específico para fallas de lógica de negocios (por ejemplo, Conflicto 409 ... 200 OK sería engañoso aquí) e incluir datos en la respuesta que indique el error comercial específico . Asegúrese de que esto sea parte del contenido de la respuesta y no del texto de estado porque algunos navegadores ignoran el texto de estado personalizado. El lenguaje que me gusta usar tiene tipos de unión que son convenientes para representar mensajes. Pero también podría definir constantes de cadena para casos de error.

Ejemplos

// error with text response
409 Conflict "safety_lock_engaged"
409 Conflict "customer_not_eligible_for_selected_discount"
// warning with JSON response
202 Accepted { "backorderedProductIds": [ 37, 476 ] }
Kasey Speakman
fuente
Los códigos de estado 4xx superiores a 400 tienen significados muy específicos. Elija 400 si su caso no está cubierto específicamente por los demás.
jpmc26
@ jpmc26 Si no uso los códigos de estado de esta manera, nunca se usan. Pero siéntase libre de usarlos de la manera correcta y adecuada en sus respuestas.
Kasey Speakman
En cierto sentido, tienes razón. Nunca se usan. Los significados elegidos para los códigos específicos no parecen ser casos de uso muy comunes para la mayoría de las aplicaciones. Esta bien. Hay muchas excepciones que tampoco escribimos para atrapar.
jpmc26
@ jpmc26 Bueno, las excepciones no son el mejor modelo a seguir . Pero claro, adelante.
Kasey Speakman
No lanzar o capturar tipos de excepción específicos es análogo a no usar códigos HTTP específicos ni ningún otro código de error. Asumí que esto sería obvio. Si un modelo de excepción es "el mejor" es completamente irrelevante para el punto.
jpmc26
5

En general, evitaría usar códigos de estado HTTP para representar errores específicos de lógica de negocios. Esto se debe a que ya tienen un significado semántico definido por el estándar mundial. Otros sistemas, nuevos desarrolladores, etc., se verán confundidos por su desviación del estándar.

Lo que encontré en investigaciones recientes similares fue que generalmente se acepta su uso 400 Bad Requesten caso de errores de validación y demás. De esta manera, utiliza un código de estado para todos los errores de lógica de negocios.

Por cierto, 409debe usarse cuando un recurso ha cambiado mientras lo estaba editando e intentó guardarlo nuevamente.

Ivo Coumans
fuente
4

Puede usar "Solicitud incorrecta" e incluir la identificación de la regla comercial violada y algunos detalles más sobre el cuerpo de la respuesta.

ninguno
fuente
No sé por qué esto fue rechazado. Así es como las empresas pueden devolver excepciones comerciales.
Skadoosh