REST códigos de estado HTTP para validación fallida o duplicado no válido

826

Estoy creando una aplicación con una API basada en REST y he llegado al punto en el que estoy especificando códigos de estado para cada solicitud.

¿Qué código de estado debo enviar para las solicitudes que fallan en la validación o cuando una solicitud intenta agregar un duplicado en mi base de datos?

He revisado http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html pero ninguno parece correcto.

¿Existe una práctica común al enviar códigos de estado?

alexn
fuente
14
Abra httpstatus.es , haga clic con el botón derecho >> Pestaña Pin: P
Salman von Abbas

Respuestas:

780

Para la falla de validación de entrada: 400 Bad Request + su descripción opcional. Esto se sugiere en el libro " RESTful Web Services ". Para envío doble: 409 Conflicto


Actualización de junio de 2014

La especificación relevante solía ser RFC2616 , que daba el uso de 400 (Solicitud incorrecta) de forma bastante limitada como

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

Por lo tanto, podría haberse argumentado que no era apropiado para errores semánticos. Pero ya no más; desde junio de 2014, la norma relevante RFC 7231 , que reemplaza a la RFC2616 anterior, da el uso de 400 (Solicitud incorrecta) más ampliamente como

el servidor no puede o no procesará la solicitud debido a algo que se percibe como un error del cliente

deamon
fuente
3
Sí, el cuerpo de la solicitud es parte de la sintaxis.
deamon
62
La mala solicitud es definitivamente la respuesta más común a este tipo de problema. La única otra alternativa es 422 Entidad no procesable. En realidad, proviene de WebDav, pero es perfectamente válido para reutilizar cualquier código de estado que se haya registrado con IANA.
Darrel Miller
19
Entonces, ¿cómo diferenciar entre datos mal formados que el servidor ni siquiera puede analizar y un error de validación? Un cliente manejaría estas dos respuestas de manera completamente diferente. Para la validación, probablemente mostrarían los errores al usuario. Para datos verdaderamente "malformados", registrarían el error para poder corregir el error en el método que genera la solicitud.
Josh Noe
18
No estoy de acuerdo con su interpretación de RFC7231, aunque dice que something perceived to be a client errortodos los ejemplos dados en este párrafo son violaciones del protocolo HTTP, no errores lógicos: sintaxis, encuadre, enrutamiento. Por lo tanto, considero que la especificación HTTP no permite 400 para la validación fallida en el nivel de la aplicación.
Dima Tisnek
2
¿Por qué no utilizar una 422 - Entidad no procesable? Me parece más lógico
java_geek
278
  • Validación fallida: 403 Prohibido ("El servidor entendió la solicitud, pero se niega a cumplirla"). Contrariamente a la opinión popular, RFC2616 no dice "403 solo está destinado a la autenticación fallida", sino "403: Sé lo que quieres, pero no haré eso". Esa condición puede o no ser debido a la autenticación.
  • Intentando agregar un duplicado: 409 Conflict ("No se pudo completar la solicitud debido a un conflicto con el estado actual del recurso")

Definitivamente debe dar una explicación más detallada en los encabezados y / o el cuerpo de la respuesta (por ejemplo, con un encabezado personalizado - X-Status-Reason: Validation failed).

Piskvor salió del edificio
fuente
17
@deamon: Esa no es la especificación, es Wikipedia, es decir, la opinión de alguien sobre "qué significan los códigos de estado HTTP"; tenga en cuenta que la página dice esencialmente "esto es lo que Apache quiere decir con 403, esto es lo que IIS significa con 403", y en ninguna parte hace referencia al RFC oficial. Parece que estás repitiendo "403 significa lo que dice Apache". NO. El RFC real (que es el documento relevante, no la implementación de Apache, ni la implementación de IIS, ni la implementación de nadie más) está aquí: w3.org/Protocols/rfc2616/rfc2616-sec10.html
Piskvor dejó el edificio el
57
"10.4.4 403 Prohibido El servidor entendió la solicitud, pero se niega a cumplirla. La autorización no ayudará y la solicitud NO DEBE repetirse. Si el método de solicitud no fue HEAD y el servidor desea hacer público por qué la solicitud no cumplido, DEBE describir el motivo del rechazo en la entidad. Si el servidor no desea poner esta información a disposición del cliente, se puede usar el código de estado 404 (No encontrado) ". No veo énfasis allí ("DEBE / NO DEBE" son palabras clave RFC 2119, no énfasis); esa es su idea de lo que significa "prohibido", no de RFC.
Piskvor salió del edificio el
10
Me gusta esta respuesta, pero aún veo un pequeño problema. Según la especificación , cuando se devuelve un 403 , "la solicitud NO DEBE repetirse". Sin embargo, devolver un 409 "solo está permitido en situaciones en las que se espera que el usuario pueda resolver el conflicto y volver a enviar la solicitud". En el caso de un duplicado, creo que 403 es más apropiado, ya que realmente no se puede resolver el conflicto (excepto eliminando la instancia anterior del recurso).
pablobm
2
Para el mensaje de error en sí, debe modificar la frase de razón, por lo que enviar el encabezado HTTP/1.0 403 Form validation errorses la forma más clara de hacerlo.
aleemb
66
OMI, 422 "Entidad no procesable" tiene mucho más sentido. Mi razonamiento es que no es que el servidor se niegue a cumplir la solicitud, es que el servidor no puede cumplir la solicitud.
tybro0103
225

Recomiendo el código de estado 422, "Entidad no procesable" .

11.2 422 Entidad no procesable

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.

Julian Reschke
fuente
11
Por supuesto, es un código de estado HTTP, consulte iana.org/assignments/http-status-codes . Hay más códigos de estado que los definidos en RFC 2616.
Julian Reschke
77
WebDAV es una extensión HTTP . "Extensiones HTTP para creación y control de versiones distribuidas web (WebDAV)" Entonces, el código de estado 422 no es un código de estado http, sino un código de estado de una extorsión de http.
deamon
16
demonio, eso no tiene sentido. HTTP define cómo definir nuevos códigos, y eso es lo que está haciendo WebDAV. Hay un registro de código de estado por una razón.
Julian Reschke
14
FYI - Descripción RFC de 422: 11.2. 422 Entidad no procesable 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 El código de estado (Solicitud incorrecta) 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.
Steve Kallestad
66
Y los hilos no 'caducan'. Deben mantenerse vivos o los principales resultados de búsqueda de Google comienzan a ser inexactos.
James Billingham el
81

200,300, 400, 500 son todos muy genéricos. Si quieres genérico, 400 está bien.

422 es utilizado por un número cada vez mayor de API e incluso Rails lo utiliza de forma inmediata.

No importa qué código de estado elija para su API, alguien estará en desacuerdo. Pero prefiero 422 porque pienso en '400 + text status' como demasiado genérico. Además, no está aprovechando un analizador listo para JSON; en contraste, un 422 con una respuesta JSON es muy explícito, y se puede transmitir una gran cantidad de información de error.

Hablando de la respuesta JSON, tiendo a estandarizar la respuesta de error de Rails para este caso, que es:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

Este formato es perfecto para la validación de formularios, que considero el caso más complejo para admitir en términos de "riqueza de informes de errores". Si su estructura de error es esta, es probable que maneje todas sus necesidades de informes de errores.

sethcall
fuente
2
¿Qué pasa con los errores derivados de las interacciones entre los argumentos? Es decir, arg1es válido y arg2es válido, pero la combinación de los dos, con los valores específicos enviados, no es válida.
Jonás
1
No lo pensaría demasiado; simplemente elija uno que parezca ser el dueño de la relación.
sethcall
o incluso solo error en ambos argumentos. Como usuario, creo que me gustaría ver el error en cada uno de los campos que están en conflicto, creo.
acurruca el
¡Agradable!. explícito es mejor que implícito
bhathiya-perera
46

200

Ugh ... (309, 400, 403, 409, 415, 422) ... muchas respuestas tratando de adivinar, argumentar y estandarizar cuál es el mejor código de retorno para una solicitud HTTP exitosa pero una llamada REST fallida .

Esta mal mezclar códigos de estado HTTP y códigos de estado REST.

Sin embargo, vi muchas implementaciones mezclándolas, y muchos desarrolladores pueden no estar de acuerdo conmigo.

Los códigos de retorno HTTP están relacionados con el HTTP Requestmismo. Una llamada REST se realiza mediante una solicitud de Protocolo de transferencia de hipertexto y funciona a un nivel inferior al método REST invocado. REST es un concepto / enfoque, y su salida es un resultado comercial / lógico , mientras que el código de resultado HTTP es de transporte .

Por ejemplo, devolver "404 No encontrado" cuando llama a / users / es confuso, porque puede significar:

  • URI está mal (HTTP)
  • No se encontraron usuarios (REST)

"403 Prohibido / Acceso denegado" puede significar:

  • Se necesita un permiso especial. Los navegadores pueden manejarlo preguntando al usuario / contraseña. (HTTP)
  • Permisos de acceso incorrectos configurados en el servidor. (HTTP)
  • Debes estar autenticado (REST)

Y la lista puede continuar con '500 Server error "(un error de Apache / Nginx HTTP lanzado o un error de restricción comercial en REST) ​​u otros errores de HTTP, etc.

Según el código, es difícil entender cuál fue la razón de la falla, una falla HTTP (transporte) o una falla REST (lógica).

Si la solicitud HTTP se realizó físicamente con éxito, siempre debe devolver el código 200, independientemente de si el registro se encuentra o no. Porque el recurso URI se encuentra y fue manejado por el servidor HTTP. Sí, puede devolver un conjunto vacío. ¿Es posible recibir una página web vacía con 200 como resultado HTTP, verdad?

En lugar de esto, puede devolver 200 códigos HTTP con algunas opciones:

  • objeto "error" en el resultado JSON si algo sale mal
  • Vaciar matriz / objeto JSON si no se encuentra ningún registro
  • Una bandera de resultado / éxito bool en combinación con opciones anteriores para un mejor manejo.

Además, algunos proveedores de Internet pueden interceptar sus solicitudes y devolverle un código HTTP 404. Esto no significa que no se encuentren sus datos, pero es algo incorrecto a nivel de transporte.

De Wiki :

En julio de 2004, el proveedor de telecomunicaciones del Reino Unido, BT Group, implementó el sistema de bloqueo de contenido Cleanfeed, que devuelve un error 404 a cualquier solicitud de contenido identificado como potencialmente ilegal por Internet Watch Foundation. Otros ISP devuelven un error "prohibido" HTTP 403 en las mismas circunstancias. La práctica de emplear errores falsos 404 como un medio para ocultar la censura también se ha informado en Tailandia y Túnez. En Túnez, donde la censura era severa antes de la revolución de 2011, la gente se dio cuenta de la naturaleza de los falsos errores 404 y creó un personaje imaginario llamado "Ammar 404" que representa "el censor invisible".

¿Por qué no simplemente responder con algo como esto?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

Google siempre devuelve 200 como código de estado en su API de geocodificación, incluso si la solicitud falla lógicamente: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes

Facebook siempre devuelve 200 para solicitudes HTTP exitosas, incluso si la solicitud REST falla: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling

Es simple, los códigos de estado HTTP son para solicitudes HTTP. REST API es suya, defina sus códigos de estado.

Marcodor
fuente
3
En realidad, el uso de códigos de estado HTTP para REST es aún más confuso en el futuro: 1) ve 4xx en la caja de herramientas de su desarrollador y no puede decir con solo mirarlo si el servidor devolvió algún valor sensible o no pudo procesar su solicitud. y luego 2) todos sus manejadores de errores / excepciones / capturas deben verificar qué servidor devolvió como respuesta (en su mayoría no lo hacen, ya que tendría que hacerlo en cada llamada de servicio) y muchas veces 3) obtiene la misma carga útil ( tipo) en la ruta de éxito y error que conduce a código complicado / duplicado ... Muy confuso de hecho.
szczepanpp
99
Esta respuesta confunde la semántica original del protocolo HTTP frente a cómo REST sobre HTTP como un estilo arquitectónico reutiliza HTTP para implementar API de servicios web. Como estilo arquitectónico, REST no es un estándar a seguir rigurosamente, es un enfoque sugerido. El uso de una respuesta 200 para una falla de validación no es correcto o incorrecto, sin embargo, es confuso para sus clientes responder que la solicitud tuvo éxito, pero en realidad falló debido a una falla de validación, un detalle importante que se oculta dentro del cuerpo de la respuesta, La semántica que el cliente debe analizar para comprender.
Kevin Hooke
55
@Marcodor si su llamada API falla pero devuelve 200 indicando éxito, ¿cómo es una buena idea? no es claro y confuso para los consumidores de su API.
Kevin Hooke
3
Corrija por muchas razones, no solo la separación de los errores HTTP vs REST. La validación REST a menudo requiere más matices. Por ejemplo, registro aceptado pero marcado como duplicado frente a rechazado por una violación de índice única. También desea un modelo de retorno consistente. El BadRequest()método .NET tiene su propio modelo de devolución que diferirá de su modelo de devolución regular. Esa es una pesadilla para analizar. @KevinHooke, devolver HTTP 200 para un error de validación REST es como decir: "Recibí su mensaje, la respuesta es no, y he aquí por qué". Al volver HTTP 400 dice: "No sé de qué estás hablando".
Neil Laslett el
55
el argumento "porque google lo hace, debe ser correcto" es una locura para mí ... está bien desafiar algo que google ha implementado a los niños. Devolver HTTP 200 para una llamada de descanso sin éxito confunde a la persona que llama de la API, debería ser 4xx y uno puede incluir un bonito JSON / XML en el cuerpo ... detengamos la locura juntos.
Jeryl Cook
43

Un duplicado en la base de datos debe ser un 409 CONFLICT .

Recomiendo usar 422 UNPROCESSABLE ENTITY para errores de validación.

Doy una explicación más larga de los códigos 4xx aquí .

Phil Parker
fuente
6

El código de estado 304 no modificado también respondería de manera aceptable a una solicitud duplicada. Esto es similar a procesar un encabezado de If-None-Matchusar una etiqueta de entidad.

En mi opinión, la respuesta de @ Piskvor es la elección más obvia de lo que percibo como la intención de la pregunta original, pero tengo una alternativa que también es relevante.

Si desea tratar una solicitud duplicada como una advertencia o notificación en lugar de un error, un código de estado de respuesta de 304No modificado yContent-Location encabezado que identifique el recurso existente sería igual de válido. Cuando la intención es simplemente garantizar que exista un recurso, una solicitud duplicada no sería un error sino una confirmación. La solicitud no es incorrecta, pero es simplemente redundante, y el cliente puede consultar el recurso existente.

En otras palabras, la solicitud es buena, pero dado que el recurso ya existe, el servidor no necesita realizar ningún procesamiento adicional.

Suncat2000
fuente
66
Entendí que 304 está destinado a operaciones GET para ayudar con el almacenamiento en caché.
Sinaesthetic
6

El adaptador ActiveRecord de Ember-Data espera 422 UNPROCESSABLE ENTITYser devuelto por el servidor. Entonces, si su cliente está escrito en Ember.js, debe usar 422. Solo entonces DS.Errors se completará con los errores devueltos. Por supuesto, puede cambiar 422 a cualquier otro código en su adaptador.

Daniel Kmak
fuente
0

406 - No aceptable

Lo que significa que esta respuesta se envía cuando el servidor web, después de realizar una negociación de contenido dirigida por el servidor, no encuentra ningún contenido que cumpla con los criterios dados por el agente de usuario.

Hasan Sefa Ozalp
fuente