Respuesta de 400 vs 422 a la POST de datos

356

Estoy tratando de averiguar cuál es el código de estado correcto para devolver en diferentes escenarios con una API "REST-like" en la que estoy trabajando. Digamos que tengo un punto final que permite POST'ing compras en formato JSON. Se parece a esto:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

¿Qué debo devolver si el cliente me envía "sales_tax" (en lugar del "impuesto" esperado)? Actualmente, estoy devolviendo un 400. Pero, comencé a cuestionarme sobre esto. ¿Realmente debería devolver un 422? Quiero decir, es JSON (que es compatible) y es JSON válido, simplemente no contiene todos los campos obligatorios.

David S
fuente

Respuestas:

419

400 Bad Request ahora parece ser el mejor código de estado HTTP / 1.1 para su caso de uso.

En el momento de su pregunta (y mi respuesta original), RFC 7231 no era una cosa; en ese momento me opuse 400 Bad Requestporque RFC 2616 dijo (con énfasis el mío):

El servidor no pudo entender la solicitud debido a una sintaxis incorrecta .

y la solicitud que describe es JSON sintácticamente válida encerrada en HTTP sintácticamente válida y, por lo tanto, el servidor no tiene problemas con la sintaxis de la solicitud.

Sin embargo, como lo señaló Lee Saferite en los comentarios , RFC 7231, que obsoleta RFC 2616, no incluye esa restricción :

El código de estado 400 (Solicitud incorrecta) indica que el servidor no puede o no procesará la solicitud debido a algo que se percibe como un error del cliente (por ejemplo, sintaxis de solicitud con formato incorrecto, enmarcado de mensaje de solicitud no válido o enrutamiento de solicitud engañoso).


Sin embargo, antes de esa nueva redacción (o si desea objetar que RFC 7231 solo es un estándar propuesto en este momento), 422 Unprocessable Entityno parece un código de estado HTTP incorrecto para su caso de uso, porque como dice la introducción a RFC 4918:

Si bien los códigos de estado proporcionados por HTTP / 1.1 son suficientes para describir la mayoría de las condiciones de error encontradas por los métodos de WebDAV, hay algunos errores que no encajan perfectamente en las categorías existentes. Esta especificación define códigos de estado adicionales desarrollados para métodos WebDAV (Sección 11)

Y la descripción de422 dice:

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.

(Tenga en cuenta la referencia a la sintaxis; sospecho que 7231 también está parcialmente obsoleto 4918)

Esto suena exactamente como su situación, pero en caso de que haya alguna duda, continúa diciendo:

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.

(Reemplace "XML" con "JSON" y creo que podemos estar de acuerdo en que es su situación)

Ahora, algunos objetarán que RFC 4918 se trata de "Extensiones HTTP para Autorización y Versiones Distribuidas en la Web (WebDAV)" y que (presumiblemente) no está haciendo nada que involucre a WebDAV, por lo que no debería usar cosas de él.

Dada la opción entre usar un código de error en el estándar original que explícitamente no cubre la situación, y uno de una extensión que describe la situación exactamente, elegiría el último.

Además, RFC 4918 Sección 21.4 se refiere al Registro de Código de Estado del Protocolo de Transferencia de Hipertexto (HTTP) de la IANA , donde se puede encontrar 422.

Propongo que es totalmente razonable que un cliente o servidor HTTP use cualquier código de estado de ese registro, siempre que lo hagan correctamente.


Pero a partir de HTTP / 1.1, RFC 7231 tiene tracción, ¡así que solo úselo 400 Bad Request!

Kristian Glass
fuente
55
Tu respuesta (422) tiene sentido para mí. Esto también es lo que utiliza Rails ( respond_with ) cuando un recurso no se pudo procesar debido a errores de validación.
Tyler Rick
11
Tenga en cuenta el uso de 422 en especificaciones que no son de WebDAV aquí: tools.ietf.org/html/rfc5789#section-2.2
Andrey Shchekin
44
Solo como una actualización, RFC 7231 tiene una descripción diferente para el código de respuesta 400 que cambia la semántica.
Lee Saferite 01 de
55
Mis disculpas: actualicé esta respuesta para reflejar el cambio en los RFC y perdí algo de claridad; Intentaré refactorizar. Es casi seguro usar 422, pero hoy en día deberías usar 400.
Kristian Glass
2
Todavía creo que la especificación podría ser mucho más clara. Los ejemplos dados en el son casos claros de que el cliente está haciendo algo mal. La situación del OP también entra en esa categoría. Sin embargo, hay casos como "Entiendo lo que estás preguntando, pero me niego a hacerlo porque hay alguna regla comercial en contra de eso" no es tan claro. No es exactamente culpa del cliente, por lo que podría aplicarse un 403, según la misma especificación: "Sin embargo, una solicitud podría estar prohibida por razones no relacionadas con las credenciales". Sin embargo, preferiría tener códigos separados para las cosas relacionadas con los permisos frente a "no se puede hacer".
Thorarin
38

400 Bad Request es el código de estado HTTP adecuado para su caso de uso. El código está definido por HTTP / 0.9-1.1 RFC.

El servidor no pudo entender la solicitud debido a una sintaxis incorrecta. El cliente NO DEBE repetir la solicitud sin modificaciones.

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 Entidad no procesable se define por RFC 4918 - WebDav. Tenga en cuenta que hay una ligera diferencia en comparación con 400, consulte el texto citado a continuación.

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.

Para mantener una interfaz uniforme, debe usar 422 solo en un caso de respuestas XML y también debe admitir todos los códigos de estado definidos por la extensión Webdav, no solo 422.

http://tools.ietf.org/html/rfc4918#page-78

Ver también la publicación de Mark Nottingham sobre códigos de estado:

es un error intentar mapear cada parte de su aplicación "profundamente" en códigos de estado HTTP; en la mayoría de los casos, el nivel de granularidad al que desea apuntar es mucho más grueso. En caso de duda, está bien usar los códigos de estado genéricos 200 OK, 400 Bad Request y 500 Internal Service Error cuando no hay un mejor ajuste .

Cómo pensar en los códigos de estado HTTP

filip26
fuente
44
El código 422 es parte del registro IANA iana.org/assignments/http-status-codes/http-status-codes.xhtml, por lo que cualquier IMHO no tiene sentido. En cualquier caso, la API REST de Facebook y Twitter reinventa sus propios códigos y no utiliza los estándares RFC / IANA. Entonces puedes hacerlo.
gavenkoa
15
La Sección 11 establece específicamente que se agregan a la especificación completa y no solo dentro de la especificación WebDav:The following status codes are added to those defined in HTTP/1.1 [RFC2616].
Steve Tauber
8
El hecho de que el código se describa como parte de la especificación de WebDAV no significa que sea específico de WebDAV. Se supone que los códigos de estado son genéricos.
trata bien tus modificaciones el
33

Para reflejar el estado a partir de 2015:

Comportamiento, tanto los códigos de respuesta 400 como 422 serán tratados de la misma manera por clientes e intermediarios, por lo que en realidad no hay una diferencia concreta con el uso.

Sin embargo, esperaría ver 400 actualmente utilizados más ampliamente, y además las aclaraciones que proporciona la especificación HTTPbis hacen que sea el más apropiado de los dos códigos de estado:

  • La especificación HTTPbis aclara la intención de 400 de no ser únicamente para errores de sintaxis. Ahora se usa la frase más amplia "indica que el servidor no puede o no procesará la solicitud debido a algo que se percibe como un error del cliente".
  • 422 es específicamente una extensión WebDAV, y no se hace referencia en RFC 2616 o en la especificación HTTPbis más reciente .

Para el contexto, HTTPbis es una revisión de la especificación HTTP / 1.1 que intenta aclarar áreas que no eran claras o inconsistentes. Una vez que haya alcanzado el estado aprobado, reemplazará a RFC2616.

Tom Christie
fuente
44
¿El 403 Prohibido también podría usarse para este contexto? Cita: El código de estado 403 (Prohibido) indica que el servidor entendió la solicitud pero se niega a autorizarla ... Si se proporcionaron credenciales de autenticación en la solicitud, el servidor las considera insuficientes para otorgar acceso ... Sin embargo, una solicitud podría estar prohibido por razones no relacionadas con las credenciales. Parece que 403 puede usarse para rechazar solicitudes fuera de la autenticación.
recolector de basura
1
@garbagecollector tenga en cuenta que "rechazado por motivos ajenos a las credenciales "! = "rechazado por motivos ajenos a la autenticación ". Hay muchas maneras de autenticar a alguien sin usar credenciales, específicamente.
Knetic
@garbagecollector no, credenciales significa autenticación ("quién es usted"), que sería 401 en caso de falla. La autorización ("qué puedes hacer") sería 403 en caso de falla. Explicación completa aquí: stackoverflow.com/a/6937030/137948 Tampoco se aplica a la situación de "campos faltantes" del OP porque el error sería el mismo independientemente del usuario que lo haya intentado. Estoy de acuerdo 400 es la respuesta correcta.
Will Sheppard
27

Estudio de caso: API de GitHub

https://developer.github.com/v3/#client-errors

Tal vez copiar de API conocidas es una buena idea:

Existen tres tipos posibles de errores de cliente en llamadas API que reciben cuerpos de solicitud:

El envío de JSON inválido dará como resultado una respuesta 400 Solicitud incorrecta.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

Enviar el tipo incorrecto de valores JSON dará como resultado una respuesta 400 Solicitud incorrecta.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

El envío de campos no válidos dará como resultado una respuesta 422 de entidad no procesable.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
Creo que esta es la respuesta correcta y comprensible.
LEMUEL ADANE
1
No puedo votarlo más. Desearía que las respuestas más votadas se refirieran a esta. Las especificaciones (RFC, IANA) no lograron proporcionar definiciones claras y distinciones entre los dos. Entonces la respuesta se reduce a las mejores prácticas y GitHub nos da una.
Alex Klaus
15

No hay una respuesta correcta, ya que depende de cuál sea la definición de "sintaxis" para su solicitud. Lo más importante es que tú:

  1. Use los códigos de respuesta de manera consistente
  2. Incluya tanta información adicional en el cuerpo de respuesta como pueda para ayudar a los desarrolladores que usan su API a descubrir qué está sucediendo. =

Antes de que todos salten sobre mí por decir que no hay una respuesta correcta o incorrecta aquí, déjenme explicarles un poco cómo llegué a la conclusión.

En este ejemplo específico, la pregunta del OP se trata de una solicitud JSON que contiene una clave diferente de la esperada. Ahora, el nombre de la clave recibida es muy similar, desde el punto de vista del lenguaje natural, a la clave esperada, pero es, estrictamente, diferente y, por lo tanto, (generalmente) no es reconocido por una máquina como equivalente.

Como dije anteriormente, el factor decisivo es lo que se entiende por sintaxis . Si la solicitud se envió con un Tipo de contenido de application/json, entonces sí, la solicitud es sintácticamente válida porque es una sintaxis JSON válida, pero no semánticamente válida, ya que no coincide con lo esperado. (suponiendo una definición estricta de lo que hace que la solicitud en cuestión sea semánticamente válida o no).

Si, por otro lado, la solicitud se envió con un Tipo de contenido personalizado más específico como application/vnd.mycorp.mydatatype+jsonese, quizás, especifica exactamente qué campos se esperan, entonces diría que la solicitud podría ser sintácticamente inválida, de ahí la respuesta 400.

En el caso en cuestión, dado que la clave era incorrecta, no el valor , hubo un error de sintaxis si había una especificación de qué claves son válidas. Si no hubiera especificación para claves válidas, o si el error fue con un valor , entonces sería un error semántico .

cdeszaq
fuente
Respuesta muy subestimada: gracias por la explicación bien redactada.
puiu
¡Exactamente mis pensamientos al respecto! Vengo del fondo XML SOAP y el concepto de esquema acaba de entrar en mi sangre y los documentos JSON en lugar de no anunciar su esquema. Para mí es si el servidor "entiende" la solicitud o no. Si el servidor no sabe qué es "sales_tax" es simplemente 400: "No tengo idea de lo que me enviaste pero definitivamente no es lo que quiero".
Aleksander Stelmaczonek
4

422 Entidad no procesable explicada Actualizado: 6 de marzo de 2017

¿Qué es la entidad 422 no procesable?

Un código de estado 422 ocurre cuando una solicitud está bien formada, sin embargo, debido a errores semánticos, no se puede procesar. Este estado HTTP se introdujo en RFC 4918 y se orienta más específicamente a las extensiones HTTP para la creación y el control de versiones distribuidas en la Web (WebDAV).

Existe cierta controversia sobre si los desarrolladores deben devolver un error 400 vs 422 a los clientes (más sobre las diferencias entre ambos estados a continuación). Sin embargo, en la mayoría de los casos, se acuerda que el estado 422 solo debe devolverse si admite las capacidades de WebDAV.

A continuación, se puede leer una definición palabra por palabra del código de estado 422 tomado de la sección 11.2 en RFC 4918.

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.

La definición continúa diciendo:

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.

Códigos de estado 400 vs 422

Los errores de solicitud incorrectos utilizan el código de estado 400 y deben devolverse al cliente si la sintaxis de la solicitud tiene un formato incorrecto, contiene un marco de mensaje de solicitud no válido o un enrutamiento de solicitud engañoso. Este código de estado puede parecer bastante similar al estado de la entidad no procesable 422, sin embargo, una pequeña información que los distingue es el hecho de que la sintaxis de una entidad de solicitud para un error 422 es correcta, mientras que la sintaxis de una solicitud que genera un 400 El error es incorrecto.

El uso del estado 422 debe reservarse solo para casos de uso muy particulares. En la mayoría de los otros casos en los que se ha producido un error del cliente debido a una sintaxis con formato incorrecto, se debe usar el estado 400 Solicitud incorrecta.

https://www.keycdn.com/support/422-unprocessable-entity/

Clojurevangelist
fuente
1

Su caso: HTTP 400 es el código de estado correcto para su caso desde la perspectiva REST, ya que es sintácticamente incorrecto enviar en sales_taxlugar de tax, aunque es un JSON válido. Normalmente, la mayoría de los marcos del lado del servidor aplican esto al asignar el JSON a los objetos. Sin embargo, hay algunas implementaciones REST que ignoran las novedades keyen el objeto JSON. En ese caso, una content-typeespecificación personalizada para aceptar solo campos válidos puede ser aplicada por el lado del servidor.

Escenario ideal para 422:

En un mundo ideal, 422 es preferible y generalmente aceptable para enviar como respuesta si el servidor comprende el tipo de contenido de la entidad de solicitud y la sintaxis de la entidad de solicitud es correcta pero no pudo procesar los datos porque es semánticamente errónea.

Situaciones de 400 sobre 422:

Recuerde, el código de respuesta 422 es un código de estado HTTP (WebDAV) extendido. Todavía hay algunos clientes HTTP / bibliotecas front-end que no están preparados para manejar 422. Para ellos, es tan simple como "HTTP 422 está mal, porque no es HTTP" . Desde la perspectiva del servicio, 400 no es muy específico.

En la arquitectura empresarial, los servicios se implementan principalmente en capas de servicios como SOA, IDM, etc. Por lo general, atienden a múltiples clientes que van desde un cliente nativo muy antiguo hasta los últimos clientes HTTP. Si uno de los clientes no maneja HTTP 422, las opciones son pedirle al cliente que actualice o cambie su código de respuesta a HTTP 400 para todos. En mi experiencia, esto es muy raro en estos días, pero sigue siendo una posibilidad. Por lo tanto, siempre se requiere un estudio cuidadoso de su arquitectura antes de decidir sobre los códigos de respuesta HTTP.

Para manejar situaciones como estas, las capas de servicio normalmente usan versioningo configuran un configurationindicador para que los clientes de conformidad HTTP estrictos envíen 400 y envíen 422 para el resto de ellos. De esta forma, brindan compatibilidad de compatibilidad con versiones anteriores para los consumidores existentes, pero al mismo tiempo brindan la capacidad para que los nuevos clientes consuman HTTP 422.


La última actualización de RFC7321 dice:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

Esto confirma que los servidores pueden enviar HTTP 400 para solicitudes no válidas. 400 ya no se refiere solo al error de sintaxis , sin embargo, 422 sigue siendo una respuesta genuina siempre que los clientes puedan manejarlo.

YuVi
fuente
1

En primer lugar, esta es una muy buena pregunta.

400 Solicitud incorrecta: cuando falta una información crítica en la solicitud

por ejemplo, el encabezado de autorización o el encabezado de tipo de contenido. Lo cual es absolutamente requerido por el servidor para entender la solicitud. Esto puede diferir de un servidor a otro.

422 Entidad no procesable: cuando el cuerpo de la solicitud no se puede analizar.

Esto es menos severo que 400. La solicitud ha llegado al servidor. El servidor ha reconocido que la solicitud tiene la estructura básica correcta. Pero la información en el cuerpo de la solicitud no se puede analizar ni comprender.

por ejemplo, Content-Type: application/xmlcuando el cuerpo de la solicitud es JSON.

Aquí hay un artículo que enumera los códigos de estado y su uso en las API REST. https://metamug.com/article/status-codes-for-rest-api.php


fuente
55
422 significa que la sintaxis es válida, pero el contenido no lo es. Enviar JSON donde se espera XML significa que la sintaxis es incorrecta, por lo que un 400 es la respuesta correcta en este caso.
Dirk
1
Exactamente como Dirk dijo 422 significa solicitud sintácticamente válida (puede analizarse y entenderse) pero semánticamente inválida
Jacek Obarymski
400: cuando la solicitud no se puede procesar debido a una sintaxis no válida (por ejemplo, error de análisis); 422: cuando la solicitud no se puede procesar debido a datos no válidos (por ejemplo, error de validación).
Kitanotori
Su ejemplo para 422 no es válido porque al enviar json con un tipo de medio de aplicación / xml, el cuerpo automáticamente es sintácticamente incorrecto y la respuesta debería ser 400.
manemarron
-15

En realidad, debe devolver "200 OK" y en el cuerpo de la respuesta incluir un mensaje sobre lo que sucedió con los datos publicados. Entonces depende de su aplicación entender el mensaje.

La cuestión es que los códigos de estado HTTP son exactamente eso: códigos de estado HTTP. Y están destinados a tener significado solo en la capa de transporte, no en la capa de aplicación. La capa de aplicación nunca debería saber que se está utilizando HTTP. Si cambió su capa de transporte de HTTP a Homing Pigeons, no debería afectar su capa de aplicación de ninguna manera.

Déjame darte un ejemplo no virtual. Digamos que te enamoras de una chica y ella te ama, pero su familia se muda a un país completamente diferente. Ella te da su nueva dirección de correo postal. Naturalmente, decides enviarle una carta de amor. Entonces escribe su carta, la pone en un sobre, escribe su dirección en el sobre, le pone un sello y la envía. Ahora consideremos estos escenarios

  1. Olvidaste escribir el nombre de una calle. Recibirá una carta sin abrir con un mensaje escrito que dice que la dirección está mal formada. Usted arruinó la solicitud y la oficina de correos receptora no puede manejarla. Eso es equivalente a recibir "400 Bad Request".
  2. Entonces arreglas la dirección y envías la carta nuevamente. Pero debido a la mala suerte, escribiste mal el nombre de la calle. Volverá a recibir la carta con un mensaje que dice que la dirección no existe. Eso es equivalente a recibir "404 no encontrado".
  3. Corrige la dirección nuevamente y esta vez logra escribir la dirección correctamente. Tu chica recibe la carta y te responde. Es el equivalente a recibir "200 OK". Sin embargo, esto no significa que le gustará lo que ella escribió en su carta. Simplemente significa que recibió su mensaje y tiene una respuesta para usted. Hasta que abra el sobre y lea su carta, no podrá saber si ella lo echa mucho de menos o si quiere romper con usted.

En resumen: devolver "200 OK" no significa que la aplicación del servidor tenga buenas noticias para usted. Solo significa que tiene algunas noticias.

PD: El código de estado 422 solo tiene un significado en el contexto de WebDAV. Si no está trabajando con WebDAV, entonces 422 tiene exactamente el mismo significado estándar que cualquier otro código no estándar = que no es ninguno.

Ir libre
fuente