¿Cuál es el código de respuesta REST adecuado para una solicitud válida pero con datos vacíos?

332

Por ejemplo, ejecuta una solicitud GET users/9pero no hay ningún usuario con ID # 9. ¿Cuál es el mejor código de respuesta?

  • 200 OK
  • 202 aceptado
  • 204 Sin contenido
  • 400 Petición Incorrecta
  • 404 No encontrado
SOY B
fuente
19
Sugerencia: ¿Encontraste el usuario 9?
Chris Pfohl
42
Sugerencia 2: ¿Entonces no se encontró el usuario 9 ?
Tomasz Nurkiewicz
18
@IMB, ¿quién dice 204? "Sin contenido" indica que la entidad que está buscando existe, pero no tiene representación. Por ejemplo, si el blog con ID 15 no tiene comentarios y no desea devolver una lista vacía para los comentarios del número de blog 15: "/ blog / 15 / comments" devolvería NoContent. Por otro lado, si el blog 15 existe, '404 no encontrado' es más apropiado.
Chris Pfohl
12
@Crisfole no quiso decir ". Por otro lado, si el blog 15 no existe, '404 Not Found' es más apropiado"
gdoron está apoyando a Monica el
15
Ciertamente lo hice @gdoron! :) Gracias. Lamentablemente, llego aproximadamente tres años tarde para editar eso y arreglarlo.
Chris Pfohl

Respuestas:

249

TL; DR: uso 404

Ver este blog . Lo explica muy bien.

Resumen de los comentarios del blog sobre 204:

  1. 204 No Content no es terriblemente útil como código de respuesta para un navegador (aunque de acuerdo con las especificaciones HTTP, los navegadores deben entenderlo como un código de respuesta 'no cambiar la vista').
  2. 204 No Content es , sin embargo, muy útil para los servicios web ajax que puede desear para indicar el éxito sin tener que devolver algo. (Especialmente en casos como DELETEo POSTs que no requieren comentarios).

La respuesta, por lo tanto, a su pregunta es el uso 404en su caso. 204es un código de respuesta especializado que a menudo no debe devolver a un navegador en respuesta a un GET.

Los otros códigos de respuesta que son incluso menos apropiados que 204y 404:

  1. 200debe devolverse con el cuerpo de lo que haya obtenido con éxito. No es apropiado cuando la entidad que estás buscando no existe.
  2. 202se usa cuando el servidor ha comenzado a trabajar en un objeto pero el objeto aún no está completamente listo. Ciertamente no es el caso aquí. No ha comenzado, ni comenzará, la construcción del usuario 9 en respuesta a una GETsolicitud. Eso rompe todo tipo de reglas.
  3. 400se utiliza en respuesta a una solicitud HTTP mal formateada (por ejemplo, encabezados http mal formados, segmentos ordenados incorrectamente, etc.). Esto seguramente será manejado por cualquier marco que esté utilizando. No debería tener que lidiar con esto a menos que esté escribiendo su propio servidor desde cero. Editar : los RFC más nuevos ahora permiten utilizar 400 para solicitudes semánticamente inválidas.

Descripción de Wikipedia de los códigos de estado HTTP es particularmente útil. También puede ver las definiciones en el documento HTTP / 1.1 RFC2616 en www.w3.org

Chris Pfohl
fuente
8
Nota: los códigos de respuesta en los 200 indican éxito. Los códigos de respuesta en los 400 indican falla. El resumen, puntos uno y dos, trata sobre el 204código de respuesta (Sin contenido).
Chris Pfohl
227
-1 ya que me opongo fuertemente al 404 como respuesta a una llamada exitosa que no tiene registros para devolver. Como desarrollador que maneja una API para una aplicación que no es web, he perdido horas de contactar a los desarrolladores de la API para rastrear por qué el punto final de API al que estaba llamando no existía, cuando en realidad lo hizo, simplemente no tenía datos a reportar. Con respecto a que un 204 no sea particularmente útil para un navegador, es un poco como la cola que mueve al perro, ya que la mayoría de los usos de los puntos finales API en nuestro universo de dispositivos inteligentes no están basados ​​en el navegador y aquellos que probablemente usan AJAX. Lamento quitar puntos, sin embargo.
Matt Cashatt
38
@MatthewPatrickCashatt eres libre de votar a tu gusto. Ahora finalmente entiendo por qué la gente me está rechazando, pero la razón sigue siendo errónea. Al recibir un 404 no significa que la ruta no tenga sentido, significa que no hay recursos en esa ubicación. Punto final. Esto es cierto si está solicitando /badurlo /user/9cuando dicho usuario no existe. Un desarrollador puede ayudar agregando una frase de razón mejor que 'No encontrado', pero no es obligatorio.
Chris Pfohl
19
@Crisfole Estoy inclinado a estar en desacuerdo (aunque no votar negativamente, seguir leyendo), basado en la definición W3 de 404 , específicamente The server has not found anything matching the Request-URI. De hecho, el servidor web / de aplicaciones ha encontrado una ACCIÓN que coincide con el URI de solicitud, aunque el servidor db no. Sin embargo, también dice This status code is commonly used when [...] no other response is applicable, así que creo que eso valida un poco su uso (incluso si no estoy de acuerdo / me gusta).
Daevin
8
No creo que estés abordando el punto que estoy diciendo: un 404 es peligrosamente confuso. Confiar en que la persona que llama verifica una frase de razón o el cuerpo de la respuesta significa que no está confiando en el código de estado, en cuyo caso no es útil.
Adrian Baker
364

Me opongo firmemente a 404 a favor de 204 o 200 con datos vacíos. O al menos uno debería usar una entidad de respuesta con el 404.

La solicitud se recibió y se procesó correctamente: activó el código de la aplicación en el servidor, por lo que no se puede decir que fue un error del cliente y, por lo tanto, toda la clase de códigos de error del cliente (4xx) no se ajusta.

Más importante aún, 404 puede suceder por una serie de razones técnicas. Por ejemplo, la aplicación se desactiva o desinstala temporalmente en el servidor, problemas de conexión de proxy y demás. Por lo tanto, el cliente no puede distinguir entre un 404 que significa "conjunto de resultados vacío" y un 404 que significa "no se puede encontrar el servicio, vuelva a intentarlo más tarde".

Esto puede ser fatal: imagine un servicio de contabilidad en su empresa que enumera todos los empleados que se deben a una bonificación anual. Desafortunadamente, la única vez que se llama devuelve un 404. ¿Eso significa que a nadie se le debe un bono o que la aplicación está inactiva para una nueva implementación?

-> Para aplicaciones que se preocupan por la calidad de sus datos, 404 sin entidad de respuesta, por lo tanto, es prácticamente imposible.

Además, muchos marcos de clientes responden a un 404 lanzando una excepción sin más preguntas. Esto obliga al desarrollador del cliente a detectar esa excepción, evaluarla y luego decidir en base a eso si registrarlo como un error que es detectado, por ejemplo, por un componente de monitoreo o si debe ignorarlo. Eso tampoco me parece bonito.

La ventaja de 404 sobre 204 es que puede devolver una entidad de respuesta que puede contener información sobre por qué no se encontró el recurso solicitado. Pero si eso es realmente relevante, entonces uno también puede considerar usar una respuesta 200 OK y diseñar el sistema de una manera que permita respuestas de error en los datos de carga útil. Alternativamente, uno podría usar la carga útil de la respuesta 404 para devolver información estructurada a la persona que llama. Si recibe, por ejemplo, una página html en lugar de XML o JSON que puede analizar, entonces ese es un buen indicador de que algo técnico salió mal en lugar de una respuesta "sin resultado" que puede ser válida desde el punto de vista de la persona que llama. O se podría usar un encabezado de respuesta HTTP para eso.

Sin embargo, preferiría un 204 o 200 con respuesta vacía. De esta forma, el estado de la ejecución técnica de la solicitud se separa del resultado lógico de la solicitud. 2xx significa "ejecución técnica bien, este es el resultado, lidiar con él".

Creo que en la mayoría de los casos debería dejarse al cliente decidir si un resultado vacío es aceptable o no. Al devolver 404 sin entidad de respuesta a pesar de una ejecución técnica correcta, el cliente puede decidir considerar los casos como errores que simplemente no son errores.

Otra analogía rápida: devolver 404 por "no se encontró ningún resultado" es como lanzar una DatabaseConnectionException si una consulta SQL no arroja resultados. Puede hacer el trabajo, pero hay muchas causas técnicas posibles que arrojan la misma excepción que luego se confundiría con un resultado válido.

Jens Wurm
fuente
30
Las razones técnicas para un "no encontrado" también se conocen como errores del servidor. Esos deberían estar en los años 500. Específicamente: "El servicio no se puede encontrar" es 503 Service Unavailable.
Chris Pfohl
43
El autor de la pregunta también estaba preguntando sobre un recurso específico: un solo usuario (no la /usersruta, sino /users/9, por ejemplo, "El usuario conocido como # 9"), por lo que su comparación 'conjunto de resultados vacío' no tiene sentido. 404 significa que el objeto no existe.
Chris Pfohl
29
404 simplemente indica que no se encontró el recurso solicitado (en este caso, el número de usuario 9). No tiene nada que ver con si se activó o no el código de la aplicación, no tiene nada que ver con si una aplicación de fondo respondió o no. Un servidor web es de lo que se trataba la pregunta, no se mencionó el proxy inverso en la pregunta.
Chris Pfohl
29
El razonamiento en esta respuesta es terriblemente incorrecto.
Kurt Spindler
21
404: el cliente pudo comunicarse con un servidor determinado, pero el servidor no pudo encontrar lo solicitado. Literalmente eso: solicitud recibida, estaba bien y correctamente formateada (solicitud incorrecta 400), estaba autenticada o pública (no autorizada 401 / prohibida 403), no era necesario el pago (pago requerido 402), el método de solicitud estaba bien (método no permitido 405 ), la solicitud de aceptación puede ser satisfecha (no aceptable 406). 200 Ok debe usarse cuando el usuario obtiene el recurso. Vacío no es un recurso. El rango 400 es para errores del cliente El rango 500 es para errores del servidor En resumen: su razonamiento está desactivado.
Derk-Jan
62

Al principio, pensé que un 204 tendría sentido, pero después de las discusiones, creo que 404 es la única respuesta correcta verdadera. Considere los siguientes datos:

Usuarios: John, Peter

METHOD  URL                      STATUS  RESPONSE
GET     /users                   200     [John, Peter]
GET     /users/john              200     John
GET     /users/kyle              404     Not found
GET     /users?name=kyle`        200     []
DELETE  /users/john              204     No Content

Algunos antecedentes:

  1. la búsqueda devuelve una matriz, simplemente no tenía coincidencias pero tiene contenido: una matriz vacía .

  2. 404 es, por supuesto, mejor conocido por las URL que no son compatibles con el servidor solicitado, pero un recurso que falta es el mismo.
    Aunque /users/:namecoincida con users/kyle, el usuario Kyle no está disponible recurso por lo que todavía se aplica un 404. No es una consulta de búsqueda, es una referencia directa por una url dinámica , por lo que es 404.

De todos modos, mis dos centavos :)

Justus Romijn
fuente
99
Arrojando mi peso detrás de este estilo para una API REST. Ningún cliente debe solicitar / users / kyle a menos que se le haya dicho que el recurso existiría a través de una llamada a / users o / users? Name = kyle
Gary Barker
@GaryBarker Pero como eso es "entrada del usuario" en algún tipo, la API todavía tiene que manejarlo correctamente. Si bien debe evitar el 404 en SU ​​cliente, no se puede garantizar que realmente se haya verificado en primer lugar. El diseño de la API debe hacerse sin considerar la implementación exacta de su cliente, especialmente en términos de la entrada del usuario comprobada.
RicoBrassers
Esta es la respuesta con la que más estoy de acuerdo. Ejemplo perfecto de cómo quiero que funcionen las API. El comentario de @ GaryBarker también es perfecto. Es un error cuando buscas algo por ID y no existe. Debe saber que existe una identificación antes de hacer la llamada. Principalmente porque obtener una respuesta vacía 'exitosa' simplemente elimina el error más adelante, probablemente para algunos 'no se puede leer el nombre de propiedad de undefined' al hacer user.name o algo así.
Jamie Twells el
¿Qué pasa con una combinación de los dos? Asumiendo que los usuarios tienen amigos. / users / kyle / friends? name = fred. Kyle no existe, entonces, ¿sería esta respuesta 404? ¿O serían 200 porque no nos importa exactamente Kyle, solo nos preocupamos por buscar a sus amigos con el nombre Fred?
JSextonn
OMI que produciría un 404, ya que es una solicitud no válida: Kyle no existe, por lo que tampoco es posible buscar a sus amigos.
Justus Romijn
23

Si se espera que el recurso exista, pero podría estar vacío, diría que podría ser más fácil obtener un 200 OK con una representación que indique que la cosa está vacía.

Prefiero que / cosas devuelvan un 200 OK con {"Elementos": []} que un 204 sin nada en absoluto, porque de esta manera una colección con 0 elementos puede tratarse de la misma manera que una colección con uno o Más artículo en él.

Simplemente dejaría el 204 Sin contenido para PUT y DELETEs, donde podría ser el caso de que realmente no haya una representación útil.

En el caso de que / thing / 9 realmente no exista, un 404 es apropiado.

j0057
fuente
1
Parece que prefiere programar contra una API utilizando una forma más abstracta llamada RPC. En lugar de acceder a los recursos siguiendo de cerca los verbos y una URL basada en recursos como customers/1/addressbook, la forma RPC es llamar a un punto final como GetCustomerAddressBooky recibir los datos o esencialmente nulo y no tener que preocuparse tanto por las complejidades de HTTP. Hay pros y contras para ambos.
The Muffin Man
2
@ The Muffin Man, no estoy seguro de cómo puedes fingir saber si prefiero REST o RPC, ni por qué es relevante para una discusión sobre qué código de estado volver a una solicitud HTTP GET.
j0057
Tuve algunos problemas horribles de almacenamiento en caché al usar 204. Chrome trataría la solicitud de manera extraña y no mostraría nada en la red y almacenaría en caché el resultado anterior. Incluso con todos los encabezados sin caché del mundo. Estoy de acuerdo con esta respuesta, 200 parece ser el mejor con una matriz / objeto vacío pasado al usuario.
Jack
22

En proyectos anteriores, he usado 404. Si no hay un usuario 9, entonces no se encontró el objeto. Por lo tanto, 404 Not Found es apropiado.

Para el objeto existe, pero no hay datos, 204 Sin contenido sería apropiado. Creo que en su caso, el objeto no existe.

Max
fuente
14

Según la publicación de w3 ,

200 OK

La solicitud ha sido exitosa. La información devuelta con la respuesta depende del método utilizado en la solicitud.

202 aceptado

La solicitud ha sido aceptada para su procesamiento, pero el procesamiento no se ha completado.

204 Sin contenido

El servidor ha cumplido la solicitud pero no necesita devolver un cuerpo de entidad, y puede querer devolver metainformación actualizada.

400 Petición Incorrecta

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

401 no autorizado

La solicitud requiere autenticación de usuario. La respuesta DEBE incluir un campo de encabezado WWW-Authenticate

404 No encontrado

El servidor no ha encontrado nada que coincida con el URI de solicitud. No se indica si la afección es temporal o permanente.

JustCode
fuente
La publicación w3 trata sobre códigos de estado HTTP. HTTP no es idéntico a REST. REST utiliza principalmente pero no necesariamente HTTP como protocolo de transporte. 404 es un código de error de transporte HTTP. Si REST sería lo mismo que HTTP, ¿no debería llamarse HTTP?
anneb
1
@anneb Como dijiste, REST usa HTTP, por lo que esta respuesta tiene mucho sentido. REST no es HTTP, REST no es un protocolo de todos modos. REST no necesita ser idéntico (o igual que HTTP) para que esta respuesta no tenga sentido.
Koray Tugay
@Koray Tugay: la búsqueda de Google también utiliza http, por lo que, según esta respuesta, la búsqueda de Google debería responder al estado HTTP 404 si nada coincide con la búsqueda.
anneb
@anneb ¿Google Search menciona una aplicación RESTful? No lo creo. Por lo tanto, la respuesta será no. Volviendo a la pregunta original y a esta respuesta en lugar de caer en una madriguera de conejo. Si Google Search algún día crea una API RESTful (o tal vez ya lo tiene, no lo sé), puede volver 204 No Contentcuando no encuentre resultados. No 404, tiene un resultado para ti, pero no tiene contenido ...
Koray Tugay
13

Para resumir o simplificar,

2xx: Datos opcionales: URI bien formado: los criterios no son parte de URI: si los criterios son opcionales, se pueden especificar en @RequestBody y @RequestParam deberían conducir a 2xx. Ejemplo: filtrar por nombre / estado

4xx: Datos esperados: URI no bien formado: los criterios son parte de URI: si los criterios son obligatorios y solo se pueden especificar en @PathVariable, deberían conducir a 4xx. Ejemplo: búsqueda por identificación única.

Por lo tanto, para la situación solicitada: "usuarios / 9" sería 4xx (posiblemente 404) Pero para "usuarios? Nombre = superhombre" debería ser 2xx (posiblemente 204)

Ashish Singh
fuente
12

Se hacen dos preguntas. Uno en el título y otro en el ejemplo. Creo que esto ha llevado en parte a la cantidad de disputas sobre qué respuesta es apropiada.

El título de la pregunta pregunta sobre datos vacíos. Los datos vacíos siguen siendo datos pero no es lo mismo que no hay datos. Esto sugiere solicitar un conjunto de resultados, es decir, una lista, quizás de /users. Si una lista está vacía, sigue siendo una lista, por lo tanto, un 204 (Sin contenido) es el más apropiado. Acaba de solicitar una lista de usuarios y se le ha proporcionado uno, simplemente no tiene contenido.

El ejemplo proporcionado en lugar pregunta acerca de un objeto específico, un usuario, /users/9. Si no se encuentra el usuario n. ° 9, no se devuelve ningún objeto de usuario. Solicitó un recurso específico (un objeto de usuario) y no se le dio porque no se encontró, por lo que es apropiado un 404.

Creo que la forma de resolver esto es si puede usar la respuesta de la manera que esperaría sin agregar ninguna declaración condicional, luego use un 204 o use un 404.

En mis ejemplos, puedo iterar sobre una lista vacía sin verificar para ver si tiene contenido, pero no puedo mostrar datos de objetos de usuario en un objeto nulo sin romper algo o agregar una verificación para ver si es nulo.

Por supuesto, podría devolver un objeto utilizando el patrón de objeto nulo si se ajusta a sus necesidades, pero eso es una discusión para otro hilo.

Caja azul
fuente
9

Después de mirar en cuestión, no debes usar 404 ¿por qué?

Basado en RFC 7231 el código de estado correcto es204

En las respuestas anteriores noté 1 pequeño malentendido:

1.- el recurso es: /users

2.- /users/8no es el recurso, esto es: el recurso /userscon parámetro de ruta8 , el consumidor tal vez no puede notarlo y no conoce la diferencia, ¡pero el editor sí y debe saber esto! ... por lo que debe devolver una respuesta precisa para los consumidores. período.

entonces:

Según el RFC: 404 es incorrecto porque /usersse encuentran los recursos , pero la lógica ejecutada usando el parámetro 8no encontró ninguno contentpara devolver como respuesta, por lo que la respuesta correcta es:204

El punto principal aquí es: 404ni siquiera se encontró que el recurso procesara la lógica interna

204es un: Encontré el recurso, la lógica se ejecutó pero no encontré ningún dato utilizando los criterios dados en el parámetro de ruta, por lo que no puedo devolverte nada. Lo siento, verifique sus criterios y vuelva a llamarme.

200: ok encontré el recurso, la lógica se ejecutó (incluso cuando no estoy obligado a devolver nada) toma esto y úsalo a tu antojo.

205: (la mejor opción para obtener una respuesta GET) Encontré el recurso, se ejecutó la lógica, tengo algo de contenido para usted, úselo bien, por cierto, si va a compartir esto en una vista, actualice la vista a muéstralo.

Espero eso ayude.

rodfraga
fuente
8

Lo que las respuestas existentes no detallan es que hace una diferencia si usa parámetros de ruta o parámetros de consulta.

  • En el caso de los parámetros de ruta, el parámetro forma parte de la ruta del recurso. En caso de /users/9, la respuesta debería ser 404porque ese recurso no se encontró. /users/9es el recurso, y el resultado es unario, o un error, no existe. Esto no es una mónada.
  • En el caso de los parámetros de consulta, el parámetro no forma parte de la ruta del recurso. En caso de /users?id=9, la respuesta debería ser 204porque /usersse encontró el recurso pero no pudo devolver ningún dato. El recurso /usersexiste y el resultado es n-ario, existe incluso si está vacío. Si ides único, esta es una mónada.

El uso de parámetros de ruta o parámetros de consulta depende del caso de uso. Prefiero parámetros de ruta para argumentos obligatorios, normativos o de identificación y parámetros de consulta para argumentos opcionales, no normativos o de atribución (como paginación, ubicación de cotejo y demás). En una API REST, me gustaría utilizar /users/9no /users?id=9especialmente debido a la posible anidamiento para conseguir "registros secundarios" como /users/9/ssh-keys/0para obtener la primera clave pública SSH o /users/9/address/2para conseguir la tercera dirección postal.

Prefiero usar 404. He aquí por qué:

  • Las solicitudes de métodos unarios (1 resultado) y n-arios (n resultados) no deberían variar sin una buena razón. Me gusta tener los mismos códigos de respuesta si es posible. El número de resultados esperados es, por supuesto, una diferencia, digamos, usted espera que el cuerpo sea un objeto (unario) o una matriz de objetos (n-aria).
  • Para n-ary, devolvería una matriz, y en caso de que no haya resultados, no devolvería ningún conjunto (ningún documento), devolvería un conjunto vacío (documento vacío, como una matriz vacía en JSON o un elemento vacío en XML ) Es decir, sigue siendo 200 pero con cero registros. No hay razón para poner esta información en el cable que no sea en el cuerpo.
  • 204Es como un voidmétodo. Yo no lo usaría para GET, sólo para POST, PUTy DELETE. Hago una excepción en caso de GETque los identificadores sean parámetros de consulta, no parámetros de ruta.
  • No encontrar el registro es como NoSuchElementException, ArrayIndexOutOfBoundsExceptiono algo así, causado por el cliente usando una identificación que no existe, por lo tanto, es un error del cliente.
  • Desde la perspectiva del código, obtener 204significa una rama adicional en el código que podría evitarse. Complica el código del cliente, y en algunos casos también complica el código del servidor (dependiendo de si usa entidades / mónadas modelo o entidades / modelos simples; y recomiendo encarecidamente mantenerse alejado de entidades / mónadas modelo, puede provocar errores desagradables porque de la mónada cree que una operación es exitosa y devuelve 200 o 204 cuando debería haber devuelto otra cosa).
  • El código del cliente es más fácil de escribir y entender si 2xx significa que el servidor hizo lo que el cliente solicitó, y 4xx significa que el servidor no hizo lo que el cliente solicitó y es culpa del cliente. No darle al cliente el registro que el cliente solicitó por identificación es culpa del cliente, porque el cliente solicitó una identificación que no existe.

Por último, pero no menos importante: consistencia

  • GET /users/9
  • PUT /users/9 y DELETE /users/9

PUT /users/9y DELETE /users/9ya tiene que regresar 204en caso de actualización o eliminación exitosa. Entonces, ¿qué deberían devolver en caso de que el usuario 9 no existiera? No tiene sentido tener la misma situación presentada como diferentes códigos de estado dependiendo del método HTTP utilizado.

Además, no es una norma, sino una razón cultural: si 204se usa para lo GET /users/9siguiente que sucederá en el proyecto es que alguien piensa que regresar 204es bueno para los métodos n-ary. Y eso complica el código del cliente, porque en lugar de simplemente verificar 2xxy luego decodificar el cuerpo, el cliente ahora tiene que verificar específicamente 204y en ese caso omitir la decodificación del cuerpo. Bud, ¿qué hace el cliente en su lugar? ¿Crear una matriz vacía? ¿Por qué no tener eso en el cable, entonces? Si el cliente crea la matriz vacía, 204 es una forma de compresión estúpida. Si el cliente usa en su nulllugar, se abre una lata de gusanos completamente diferente.

Christian Hujer
fuente
3

204 es más apropiado. Especialmente cuando tiene un sistema de alerta para garantizar que su sitio web sea seguro, 404 en este caso causaría confusión porque no sabe que algunas alertas 404 son errores de backend o solicitudes normales, pero la respuesta está vacía.

刘武豪
fuente
No debería devolver 404 si tiene un error de back-end.
espantoso22
3

Yo diría que ninguno de los dos es realmente apropiado. Como se ha dicho, por ejemplo, por @anneb, yo también creo que parte de los problemas surge del uso de un código de respuesta HTTP para transportar un estado relacionado con un servicio RESTful. Todo lo que el servicio REST tenga que decir sobre su propio procesamiento debe ser transportado por medio de códigos específicos REST.

1

Yo diría que, si el servidor HTTP encuentra algún servicio que esté listo para responder a una solicitud que se envió, no debería responder con un HTTP 404, al final, el servidor encontró algo, a menos que el servidor lo indique explícitamente servicio que procesa la solicitud.

Asumamos por un momento la siguiente URL: http://example.com/service/return/test.

  • El caso A es que el servidor "simplemente está buscando el archivo en el sistema de archivos". Si no está presente, 404es correcto. Lo mismo es cierto, si solicita algún tipo de servicio para entregar exactamente este archivo y ese servicio le dice que no existe nada de ese nombre.
  • En el caso B, el servidor no funciona con archivos "reales", pero en realidad la solicitud es procesada por otro servicio, por ejemplo, algún tipo de sistema de plantillas. Aquí, el servidor no puede hacer ningún reclamo sobre la existencia del recurso, ya que no sabe nada al respecto (a menos que el servicio lo maneje).

Sin ninguna respuesta del servicio que requiera explícitamente un comportamiento diferente, el servidor HTTP solo puede decir 3 cosas:

  • 503 si el servicio que se supone que maneja la solicitud no se está ejecutando o no responde;
  • 200 de lo contrario, ya que el servidor HTTP puede satisfacer la solicitud, sin importar lo que diga el servicio más adelante;
  • 400o 404para indicar que no existe tal servicio (en oposición a "existe pero fuera de línea") y no se encontró nada más.

2

Para volver a la pregunta en cuestión: creo que el enfoque más limpio sería no utilizar un código de respuesta HTTP en absoluto que no sea el dicho anteriormente. Si el servicio está presente y responde, el código HTTP debe ser 200. La respuesta debe contener el estado que el servicio devolvió en un encabezado separado; aquí, el servicio puede decir

  • REST:EMPTYpor ejemplo, si se le pidió que buscara algo. y esa investigación volvió vacía;
  • REST:NOT FOUNDsi se le pidió específicamente algo "ID-like" - ya sea un nombre de archivo o un recurso por ID o entrada No. 24, etc. - y ese recurso específico no se encontró (generalmente, se solicitó un recurso específico y no se encontró);
  • REST:INVALID si alguna parte de la solicitud que se envió no es reconocida por el servicio.

(tenga en cuenta que tengo el prefijo "REST:" a propósito para marcar el hecho de que, si bien estos pueden tener los mismos valores o palabras que los códigos de respuesta HTTP, son algo completamente diferentes)

3

Volvamos a la URL anterior e inspeccionemos el caso B, donde el servicio indica al servidor HTTP que no maneja esta solicitud sino que la pasa SERVICE. HTTP solo sirve lo que se le devuelve SERVICE, no sabe nada acerca de la return/testporción que se maneja SERVICE. Si ese servicio se está ejecutando, HTTP debería regresar 200ya que de hecho encontró algo para manejar la solicitud.

El estado devuelto por SERVICE(y que, como se dijo anteriormente, le gustaría ver en un encabezado separado) depende de qué acción se espera realmente:

  • if return/testsolicita un recurso específico: si existe, devuélvalo con un estado de REST:FOUND; si ese recurso no existe, regrese REST:NOT FOUND; esto podría extenderse para que regrese REST:GONEsi sabemos que alguna vez existió y no volverá, y REST:MOVEDsi sabemos que se ha ido a Hollywood
  • si return/testse considera una operación de búsqueda o de filtro: si el conjunto de resultados está vacío, devuelve un conjunto vacío en el tipo solicitado y un estado de REST:EMPTY; un conjunto de resultados en el tipo solicitado y un estado deREST:SUCCESS
  • if return/testno es una operación reconocida por SERVICE: return REST:ERRORsi está completamente equivocado (por ejemplo, un error tipográfico retrun/test), o REST:NOT IMPLEMENTEDen caso de que esté planeado para más adelante.

4 4

Esta distinción es mucho más limpia que mezclar las dos cosas diferentes. También facilitará la depuración y el procesamiento solo un poco más complejo, si es que lo hace.

  • Si se devuelve un HTTP 404, el servidor me dice: "No tengo idea de lo que estás hablando". Si bien la parte REST de mi solicitud podría estar bien, estoy buscando par'Mach en todos los lugares equivocados.
  • Por otro lado, HTTP 200 y REST: ERR me dicen que obtuve el servicio pero hice algo mal en mi solicitud al servicio.
  • Desde HTTP 200 y REST: VACÍO, sé que no hice nada malo: servidor correcto, el servidor encontró el servicio, solicitud correcta al servicio, pero el resultado de la búsqueda está vacío.

Resumen

El problema y la discusión surgen del hecho de que los códigos de respuesta HTTP se están utilizando para denotar el estado de un servicio cuyos resultados son atendidos por HTTP, o para denotar algo. eso no está dentro del alcance del servidor HTTP en sí. Debido a esta discrepancia, la pregunta no puede responderse y todas las opiniones están sujetas a mucha discusión.

El estado de una solicitud procesada por un servicio y no por el servidor HTTP REALMENTE NO DEBE (RFC 6919) ser dada por un código de respuesta HTTP. El código HTTP DEBE (RFC 2119) solo contiene información que el servidor HTTP puede proporcionar desde su propio alcance: es decir, si se encontró que el servicio procesó la solicitud o no.

En cambio, DEBE usarse una forma diferente para informar al consumidor sobre el estado de la solicitud al servicio que realmente está procesando la solicitud. Mi propuesta es hacerlo a través de un encabezado específico. Idealmente, tanto el nombre del encabezado como su contenido siguen un estándar que facilita a los consumidores trabajar con estas respuestas.

dariok
fuente
2

De acuerdo con el RFC7231 - page59 ( https://tools.ietf.org/html/rfc7231#page-59 ) la definición de respuesta de código de estado 404 es:

6.5.4. 404 no encontrado El código de estado 404 (no encontrado) indica que el servidor de origen no encontró una representación actual para el recurso de destino o no está dispuesto a revelar que existe. Un código de estado 404 no indica si esta falta de representación es temporal o permanente; se prefiere el código de estado 410 (Desaparecido) sobre 404 si el servidor de origen sabe, presumiblemente por algún medio configurable, que es probable que la condición sea permanente. Una respuesta 404 se puede almacenar en caché de manera predeterminada; es decir, a menos que la definición del método o los controles de caché explícitos indiquen lo contrario (consulte la Sección 4.2.2 de [RFC7234]).

Y lo principal que genera dudas es la definición de recurso en el contexto anterior. Según el mismo RFC (7231) la definición de recurso es:

Recursos: El objetivo de una solicitud HTTP se denomina "recurso". HTTP no limita la naturaleza de un recurso; simplemente define una interfaz que podría usarse para interactuar con los recursos. Cada recurso se identifica mediante un Identificador Uniforme de Recursos (URI), como se describe en la Sección 2.7 de [RFC7230]. Cuando un cliente construye un mensaje de solicitud HTTP / 1.1, envía el URI de destino en una de varias formas, como se define en (Sección 5.3 de [RFC7230]). Cuando se recibe una solicitud, el servidor reconstruye un URI de solicitud efectivo para el recurso de destino (Sección 5.5 de [RFC7230]). Un objetivo de diseño de HTTP es separar la identificación de recursos de la semántica de solicitud, lo cual es posible al otorgar la semántica de solicitud en el método de solicitud (Sección 4) y algunos campos de encabezado de modificación de solicitud (Sección 5).

Entonces, según tengo entendido, el código de estado 404 no debe usarse en una solicitud GET exitosa con un resultado vacío (por ejemplo, una lista sin resultado para un filtro específico)

Filipe Moisés
fuente
2

Tales cosas pueden ser subjetivas y hay algunos argumentos sólidos interesantes y diversos en ambos lados. Sin embargo [en mi opinión] devolver un 404 por datos faltantes no es correcto . Aquí hay una descripción simplificada para aclarar esto:

  • Solicitud: ¿Puedo tener algunos datos por favor?
  • Recurso (punto final de la API): recibiré esa solicitud por usted, aquí [envía una respuesta de datos potenciales]

No se rompió nada, se encontró el punto final, y se encontraron la tabla y las columnas, por lo que la base de datos consultada y los datos se devolvieron "con éxito".

Ahora, si esa "respuesta exitosa" tiene datos o no, no importa, usted solicitó una respuesta de datos "potenciales" y esa respuesta con datos "potenciales" se cumplió. Nulo, vacío, etc. son datos válidos.

200 solo significa que cualquier solicitud que hicimos fue exitosa. Estoy solicitando datos, nada salió mal con HTTP / REST, y como los datos (aunque vacíos) fueron devueltos, mi "solicitud de datos" fue exitosa.

¡Devuelva un 200 y deje que el solicitante trate con datos vacíos ya que cada escenario específico lo garantiza!

Considere este ejemplo:

  • Solicitud: consulta de tabla de "infracciones" con ID de usuario 1234
  • Recurso (punto final de API): devuelve una respuesta pero los datos están vacíos

Esta información está vacía es completamente válida. Significa que el usuario no tiene infracciones. Este es un 200 ya que todo es válido, como entonces puedo hacer:

No tienes infracciones, ¡come un muffin de arándanos!

Si consideras que es un 404, ¿qué estás diciendo? ¿No se pudieron encontrar las infracciones del usuario? Ahora, gramaticalmente eso es correcto, pero simplemente no es correcto en el mundo REST si el éxito o el fracaso se trata de la solicitud. Los datos de "infracción" para este usuario se pueden encontrar con éxito, hay cero infracciones, un número real que representa un estado válido.


[Nota descarada ..]

En su título, acepta inconscientemente que 200 es la respuesta correcta:

¿Cuál es el código de respuesta REST adecuado para una solicitud válida pero con datos vacíos?


Aquí hay algunas cosas a tener en cuenta al elegir qué código de estado usar, independientemente de la subjetividad y las elecciones difíciles:

  1. La consistencia . Si usa 404 para "sin datos", úselo cada vez que una respuesta no devuelva datos.
  2. No use el mismo estado para más de un significado . Si devuelve 404 cuando no se encontró un recurso (p. Ej., El punto final de la API no existe, etc.), entonces no lo use también para no devolver datos. Esto solo hace que lidiar con las respuestas sea un dolor.
  3. Considere el contexto cuidadosamente . ¿Qué es la "solicitud"? ¿Qué estás diciendo que estás tratando de lograr?
James
fuente
1

Codifique el contenido de la respuesta con una enumeración común que permita al cliente activarlo y bifurcar la lógica en consecuencia. No estoy seguro de cómo distinguiría su cliente la diferencia entre un 404 de "datos no encontrados" y un 404 de "recurso web no encontrado". No desea que alguien busque el usuario Z / 9 y que el cliente se pregunte si la solicitud era válida pero no se devolvieron datos.

Adelante
fuente
1

¿Por qué no usar 410? Sugiere que el recurso solicitado ya no existe y se espera que el cliente nunca haga una solicitud para ese recurso, en su caso users/9.

Puede encontrar más detalles sobre 410 aquí: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Akshat
fuente
2
`` se espera que el cliente nunca haga una solicitud '', y si su usuario se crea más tarde, su respuesta sugiere que podría garantizar que este usuario nunca existirá, es una suposición muy audaz y probablemente errónea
Holly
Lo que dijo Holly. Para agregar a su punto: incluso en caso de que el usuario haya existido y haya sido eliminado, 410 está mal, porque ¿qué pasa si el usuario se recupera? (¿Qué tipo de caso especial se crea más tarde?)
Christian Hujer
porque 410 debería ser una situación permanente. restapitutorial.com/httpstatuscodes.html
Akostha
1

Es triste que algo tan simple y bien definido se haya "basado en la opinión" en este hilo.

Un servidor HTTP solo conoce "entidades", que es una abstracción de cualquier contenido, ya sea una página web estática, una lista de resultados de búsqueda, una lista de otras entidades, una descripción json de algo, un archivo multimedia, etc.

Se espera que cada entidad sea identificable por una URL única, por ejemplo

  • / user / 9 - una sola entidad: una ID DE USUARIO = 9
  • / users - una sola entidad: una LISTA de todos los usuarios
  • /media/x.mp3: una sola entidad: un ARCHIVO multimedia llamado x.mp3
  • / search - una sola entidad: un CONTENIDO dinámico basado en parámetros de consulta

Si un servidor encuentra un recurso por la URL dada, no importa cuál sea su contenido - 2G de datos, nulo, {}, [] - mientras exista, será 200. Pero si dicha entidad es desconocido para el servidor, se ESPERA que devuelva 404 "No encontrado".

Una confusión parece ser de los desarrolladores que piensan que si la aplicación tiene un controlador para una determinada forma de ruta, no debería ser un error. A los ojos del protocolo HTTP, no importa lo que sucedió en las partes internas del servidor (es decir, si el enrutador predeterminado respondió o un controlador para una forma de ruta específica), siempre que no haya una entidad coincidente en el servidor con el servidor. URL solicitada (que solicitó un archivo MP3, página web, objeto de usuario, etc.), que devolvería contenidos válidos (vacíos o no), debe ser 404 (o 410, etc.).

Otro punto de confusión parece estar en torno a "sin datos" y "sin entidad". El primero trata sobre el contenido de una entidad, y el segundo sobre su existencia.

Ejemplo 1:

  • Sin datos: / users devuelve 200 OK, cuerpo: [] porque nadie se ha registrado todavía
  • Ninguna entidad: / users devuelve 404 porque no hay ruta / users

Ejemplo 2

  • Sin datos: / user / 9 devuelve return 200 OK, body: {}, porque el ID de usuario = 9 nunca ingresó sus datos personales
  • Ninguna entidad: / user / 9 devuelve 404 porque no hay ID de usuario = 9

Ejemplo 3

  • Sin datos: / search? Name = Joe devuelve 200 OK [], porque no hay Joe's en el DB
  • Ninguna entidad: / search? Name = Joe devuelve 404 porque no hay ruta / búsqueda
Darko Maksimovic
fuente
0

404 sería muy confuso para cualquier cliente si regresa solo porque no hay datos en respuesta.

Para mí, el Código de respuesta 200 con un cuerpo vacío es suficiente para entender que todo es perfecto, pero no hay datos que coincidan con los requisitos.

energía oscura
fuente
0

Como muchos afirman, 404 es engañoso y no permite que el cliente discrimine si la uri de solicitud no existe o si la uri solicitada no puede obtener el recurso solicitado.

Se espera que el estado 200 contenga datos de recursos, por lo que no es la opción correcta. El estado 204 significa algo completamente distinto y no debe usarse como respuesta para solicitudes GET.

Todos los demás estados existentes no son aplicables, por una razón u otra.

He visto este tema discutido una y otra vez en varios lugares. Para mí, es dolorosamente obvio que para eliminar la confusión en torno al tema, se necesita un estado de éxito dedicado. Algo así como " 209 - No hay recursos para mostrar".

Será un estado 2xx porque no encontrar una ID no debería considerarse un error del cliente (si los clientes supieran todo lo que está en la base de datos del servidor, no tendrían que preguntarle nada al servidor, ¿verdad?). Este estado dedicado abordará todos los problemas debatidos con el uso de otros estados.

La única pregunta es: ¿cómo hago para que RFC acepte esto como estándar?

Bar Umberto
fuente