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

Estoy construyendo 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 donde una solicitud intenta agregar un duplicado en mi base de datos?

Miré en http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html pero ninguno de ellos parece correcto.

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

  • Error de validación: 403 Forbidden (“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 deberse a la autenticación.
  • Intentando agregar un duplicado: 409 Conflicto (“La solicitud no pudo completarse debido a un conflicto con el estado actual del recurso”).

Definitivamente debería 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 ).

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 entiende 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 syntax de la entidad de solicitud es correcta (por lo tanto, 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.

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

422 es utilizado por un número creciente de API, e incluso es utilizado por Rails fuera de la caja.

No importa qué código de estado elijas para tu API, alguien estará en desacuerdo. Pero prefiero 422 porque pienso en ‘400 + texto’ 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 respaldar 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.

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í: http://parker0phil.com/2014/10/16/REST_http_4xx_status_codes_syntax_and_sematics/

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 de descanso fallida .

Es incorrecto mezclar códigos de protocolo HTTP y resultados REST.

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

Los códigos de retorno HTTP están relacionados con la HTTP Request . Una llamada REST se realiza utilizando una solicitud de Protocolo de transferencia de hipertexto y funciona en un nivel inferior al método REST invocado en sí. 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 / confunde, porque puede significar:

  • URI es incorrecto (HTTP)
  • No se encontraron usuarios (REST)

“403 prohibido / acceso denegado” puede significar:

  • Permiso especial necesario. Los navegadores pueden manejarlo preguntando al usuario / contraseña. (HTTP)
  • Permisos de acceso incorrectos configurados en el servidor. (HTTP)
  • Necesita estar autenticado (REST)

Y la lista puede continuar con ‘Error del servidor 500’ (un error HTTP arrojado por Apache / Nginx o un error de restricción empresarial en REST) ​​u otros errores HTTP, etc.

Desde el código, es difícil entender cuál fue el motivo del error, una falla HTTP (transporte) o una falla REST (lógica).

Si la solicitud HTTP se realizó físicamente correctamente, siempre debe devolver el código 200, independientemente de los registros encontrados o no. Porque el recurso de 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 de http, correcto?

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

  • Objeto “error” en el resultado de JSON si algo sale mal
  • Matriz / objeto JSON vacío si no se encuentra ningún registro
  • Un indicador de resultado / éxito de 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 sus datos no se encuentran, pero es algo incorrecto en el nivel de transporte.

De Wiki :

En julio de 2004, el proveedor de telecomunicaciones del Reino Unido BT Group implementó el sistema de locking 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 HTTP 403 “prohibido” en las mismas circunstancias. La práctica de emplear errores falsos 404 como medio para ocultar la censura también se ha informado en Tailandia y Túnez. En Túnez, donde la censura fue 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 geoencoding, incluso si la solicitud falla lógicamente: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes

El código de estado 304 no modificado también haría una respuesta aceptable a una solicitud duplicada. Esto es similar al procesamiento de un encabezado de If-None-Match usando una etiqueta de entidad.

En mi opinión, la respuesta de @ Piskvor es la elección más obvia de lo que percibo es 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 como un error, un código de estado de respuesta del encabezado 304 No modificado y Content-Location identifique el recurso existente sería igual de válido. Cuando la intención es simplemente asegurar 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.

El adaptador ActiveRecord de Ember-Data espera que 422 UNPROCESSABLE ENTITY sea ​​devuelta desde el servidor. Por lo tanto, 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.