¿Cuál es la respuesta apropiada del código de estado HTTP para una solicitud fallida general (no es un error)?

109

Estoy creando una API RESTful que procesará una serie de interacciones del usuario, incluida la realización de pedidos con tarjetas de crédito almacenadas.

En el caso de un pedido exitoso, devuelvo un 200 OK, y en el caso de que la solicitud de pedido esté mal formada o no sea válida, devuelvo un 400 Bad Request. Pero, ¿qué debo devolver si hay algún problema durante el procesamiento real del pedido?

  1. El cliente envía un pedido al servidor para un recurso de usuario. Si el usuario no existe, se devuelve 404 Not Found.
  2. Se valida el formato y la información del pedido. Si no es válido, se devuelve 400 Bad Request.
  3. Se procesa el pedido. Si el pedido tiene éxito, se devuelve un 201 Created para el pedido. Si se encuentra un error inesperado, se devuelve un 500 Server Error.

El último paso es el problema: ¿qué devuelvo si el pedido no se completa por algún otro motivo? Los posibles escenarios podrían incluir:

  • Producto agotado
  • Se alcanzó el límite máximo de pedidos del usuario
  • Error en la transacción de la tarjeta de crédito (fondos insuficientes, etc.)

Esto no parece que sea apropiado ni para 400 ni para 500. En todo caso, podría verlo como 400 si no hay un código mejor: la solicitud no era válida según las reglas comerciales. Simplemente no parece exacto.

Editar: También encontré esta discusión existente sobre el mismo tema. Todas las respuestas allí parecen apuntar al uso de códigos de estado para este tipo de infracción, con cierta discusión entre el uso de la extensión 400, 409 o 422.

Raelshark
fuente
8
Me gusta '422 entidad no procesable' para errores de validación. Y lo utilizaría para sus ejemplos anteriores, incluir un mensaje en la respuesta a la cuestión de negocio real "del producto está agotado" y, posiblemente, añadir sus propios 'códigos' si las necesidades de los clientes a programación hacen diferentes decisiones en base a la respuesta
house9
antes de saltar a 422, considere si es compatible con las capacidades de WebDAV
Mbithy Mbithy

Respuestas:

90

Debe utilizar 400 para las reglas comerciales. No devuelva 2xx si el pedido no fue aceptado. HTTP es un protocolo de aplicación, nunca lo olvides. Si devuelve 2xx, el cliente puede asumir que el pedido fue aceptado, independientemente de la información que envíe en el cuerpo.


Del libro de recetas de servicios web RESTful :

Un error común que cometen algunos servicios web es devolver un código de estado que refleja el éxito (códigos de estado de 200 a 206 y de 300 a 307) pero incluyen un cuerpo de mensaje que describe una condición de error. Hacer esto evita que el software compatible con HTTP detecte errores. Por ejemplo, un caché lo almacenará como una respuesta exitosa y lo servirá a los clientes posteriores incluso cuando los clientes puedan realizar una solicitud exitosa.

Dejaré que usted decida entre 4xx y 5xx, pero debe usar un código de estado de error.

Max Toro
fuente
1
¿Tiene algunos ejemplos o referencias para este enfoque frente al otro? Tanto su respuesta como la de Widor tienen sentido, una desde la perspectiva de HTTP como protocolo de aplicación, y la otra, ya que es estrictamente para el propósito de la transferencia. La especificación lo define como un "protocolo de nivel de aplicación", que es un poco vago. También he visto perspectivas y ejemplos en la web al investigar esto.
Raelshark
esto es tan cierto.
Young Hyun Yoo
2
¿Quiere decir "Debería utilizar 4xx para las reglas comerciales"?
Yawar
28

Debe usar 4xx para un error de cliente si el cliente puede modificar la solicitud para evitar el error. Use un 5xx para un error del servidor que el cliente realmente no puede solucionar.

El producto agotado sería un error del servidor. El cliente no puede modificar la solicitud de alguna manera para evitar el error. Podría cambiar a otro producto, pero ¿no sería una nueva solicitud?

El límite máximo de pedidos del usuario alcanzado también es un error del servidor. El cliente no puede hacer nada para solucionar ese error.

La falla en la transacción de la tarjeta de crédito sería un error del cliente. El cliente podría volver a enviar la solicitud con un método de pago o número de tarjeta de crédito diferente para solucionar el error.

Paul Morgan
fuente
6
Si se alcanza el límite de pedidos, ¿no debería el cliente alertar al usuario sobre eso y permitirle cambiar su solicitud de manera apropiada? Eso parece un error 4xx. Lo mismo ocurre con el producto que se agota. Los errores 5xx están destinados a errores causados ​​por una falla del sistema de alguna manera, no a una acción que no está permitida por una regla comercial.
carlin.scott
7
Estoy de acuerdo con el comentario anterior. Los errores 5xx son para cuando el servidor tiene problemas. Errores 4xx para reglas comerciales.
Merc
21

Tipo de error:

4×× Client Error

Código de error:

422 Unprocessable Entity

El servidor comprende el tipo de contenido de la entidad de solicitud (por lo tanto, un código de estado 415 Unsupported Media Type es inapropiado), y la sintaxis de la entidad de solicitud es correcta (por lo tanto, un código de estado 400 Bad Request es inapropiado) pero no pudo procesar el contenido instrucciones.

Por ejemplo, esta condición de error puede ocurrir si el cuerpo de una solicitud XML contiene instrucciones XML bien formadas (es decir, sintácticamente correctas), pero semánticamente erróneas.

https://httpstatuses.com/422

stamster
fuente
16

Sé que esta pregunta es antigua, pero hoy se me ocurrió la misma pregunta. Si mi usuario se queda sin créditos, ¿qué código de estado debería devolver mi API REST?

Tiendo a inclinarme hacia 402 Payment Required:

Según Wikipedia :

Reservado para uso futuro. La intención original era que este código pudiera usarse como parte de alguna forma de efectivo digital o esquema de micropagos, pero eso no ha sucedido y este código no se usa generalmente. La API de Google Developers usa este estado si un desarrollador en particular ha superado el límite diario de solicitudes.

Y de hecho lo hacen :

PAYMENT_REQUIRED (402)

  • Se alcanzó un límite de presupuesto diario establecido por el desarrollador.
  • La operación solicitada requiere más recursos de los que permite la cuota. Se requiere pago para completar la operación.
  • La operación solicitada requiere algún tipo de pago por parte del usuario autenticado.
Benjamín
fuente
Esta es la respuesta más lógica y bien pensada.
GTodorov
5

¿Qué tal 424 Failed Dependency? La especificación lo describe como:

El método no se pudo realizar en el recurso porque la acción solicitada dependía de otra acción y esa acción falló.

Pero también existe esta definición :

El código de estado 424 está definido en el estándar WebDAV y es para un caso en el que el cliente necesita cambiar lo que está haciendo; el servidor no tiene ningún problema aquí.

Puede decirle al cliente (o fingir) que tiene acciones internas que se supone que deben crear el pedido y deducir el saldo, y que una de esas acciones falló, aunque por razones perfectamente válidas, y es por eso que la solicitud falló.

Por lo que puedo ver, "acción" es un término bastante amplio y se puede usar en una variedad de situaciones, incluyendo stock insuficiente, crédito insuficiente o noche de fiesta en el almacén.


Otra opción puede ser 422 Unprocessable Entity:

El servidor comprende el tipo de contenido de la entidad de solicitud (por lo tanto, un código de estado 415 Unsupported Media Type es inapropiado), y la sintaxis de la entidad de solicitud es correcta (por lo tanto, un código de estado 400 Bad Request es inapropiado) pero no pudo procesar el contenido instrucciones.

Por ejemplo, esta condición de error puede ocurrir si el cuerpo de una solicitud XML contiene instrucciones XML bien formadas (es decir, sintácticamente correctas), pero semánticamente erróneas.

Intentar solicitar un artículo que está agotado, o cuando no tienes crédito suficiente, puede considerarse un error a nivel semántico.

MozDev dice que esto indica un error del lado del cliente, específicamente: El cliente no debe repetir esta solicitud sin modificaciones.

Loopback 4 usa 422 cuando falla la validación de entrada.


Podría decirse que un stock insuficiente o una noche de fiesta en el almacén podrían considerarse estados temporales, por lo que la solicitud podría volver a intentarse más tarde. Esa situación puede ser indicada por503 Service Unavailable

Actualmente, el servidor no puede manejar la solicitud debido a una sobrecarga temporal o un mantenimiento programado, que probablemente se aliviará después de algún retraso.

El servidor PUEDE enviar un campo de encabezado Retry-After para sugerir una cantidad de tiempo adecuada para que el cliente espere antes de volver a intentar la solicitud.

joeytwiddle
fuente
Ninguno de ellos se relaciona con un pago. ¡Voy con 402 de la respuesta anterior!
GTodorov
2

No creo que 400 se pueda utilizar para todo el escenario empresarial. Se puede utilizar para la validación básica de la entrada de datos. Más allá de eso, es posible que tengamos dificultades para ajustar otra lógica comercial en este código de error. El error manejado por esto son principalmente errores de tiempo de diseño que el desarrollador encontrará posiblemente durante la codificación del cliente.

Digamos que todos los parámetros son correctos y digamos que estamos pasando el número de cuenta de usuario a la solicitud.

Entonces, la solicitud ya no es una solicitud incorrecta, el servidor puede aceptar la solicitud. Pero ahora se niega a completar la solicitud basándose en la nueva información disponible, que es: la cuenta no tiene saldo suficiente.

Sugeriría que deberíamos usar 403 con el mensaje de error apropiado en esos escenarios.

Otro posible código de error podría ser el conflicto 409. Pero eso se usa en escenarios donde el recurso está en un estado consistente.

Rajender Saini
fuente
-1

Yo voy con 406 Not Acceptable.

Aquí hay una lista 4xx:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585
Mahmoud Zalt
fuente
8
Si bien el nombre del código de estado 406 puede parecer exacto por sí solo, debe tener en cuenta que cada código de estado tiene una descripción textual autorizada. La descripción del código de estado 406 no es adecuada para el caso que nos ocupa. Consulte httpstatuses.com/406 , por ejemplo.
Zero3
1
@ Zero3 tiene razón, este código significa que el tipo de respuesta no es aceptable, ya que hay una falta de coincidencia entre los encabezados de aceptación enviados desde el cliente y los tipos de medios enviados por el punto final, por ejemplo, aplicación / json frente a texto / sin formato
Gregor