tutorial - rest para dummies
¿Cuál es el código de respuesta REST adecuado para una solicitud válida pero para datos vacíos? (12)
Por ejemplo, ejecuta una solicitud GET para los users/9
pero 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
¿Por qué no usar 410? Sugiere que el recurso solicitado ya no existe y se espera que el cliente nunca realice 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
204 es más apropiado. Especialmente cuando tiene un sistema de alerta para asegurarse de que su sitio web sea seguro, 404 en este caso causaría confusión porque no sabe que algunas alertas 404 son errores de back-end o solicitudes normales, pero la respuesta está vacía.
Al principio, pensé que un 204 tendría sentido, pero después de las discusiones, creo que 404 es la única respuesta correcta. 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:
la búsqueda devuelve una matriz, simplemente no tiene ninguna coincidencia pero tiene contenido: una matriz vacía .
Por supuesto, 404 es mejor conocido por las URL que no son compatibles con el servidor solicitado, pero un recurso faltante es, de hecho, el mismo.
A pesar de que/users/:name
coincide conusers/kyle
, el usuario Kyle no es un recurso disponible, por lo que aún se aplica un 404. No es una consulta de búsqueda, es una referencia directa de una URL dinámica , por lo que es 404.
De todos modos, mis dos centavos :)
Codifique el contenido de la respuesta con una enumeración común que permita al cliente activarlo y bifurque la lógica en consecuencia. No estoy seguro de cómo su cliente distinguiría la diferencia entre un "datos no encontrados" 404 y un "recurso web no encontrado" 404? No desea que alguien navegue hasta el usuario Z / 9 y haga que el cliente se pregunte si la solicitud era válida pero no se devolvió ningún dato.
En proyectos anteriores, he usado 404. Si no hay un usuario 9, entonces no se encontró el objeto. Por lo tanto, 404 No encontrado es apropiado.
Para el objeto existe, pero no hay datos, 204 No Contenido sería apropiado. Creo que en tu caso, el objeto no existe sin embargo.
Hay dos preguntas formuladas. Uno en el título y otro en el ejemplo. Creo que esto ha llevado en parte a la cantidad de disputa sobre qué respuesta es apropiada.
La pregunta titula sobre datos vacíos. Los datos vacíos siguen siendo datos pero no son lo mismo que no hay datos. Así que 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 su lugar pregunta sobre un objeto específico, un usuario, /users/9
. Si no se encuentra el usuario # 9, no se devuelve ningún objeto de usuario. Usted solicitó un recurso específico (un objeto de usuario) y no se le dio porque no se encontró, por lo que un 404 es apropiado.
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 de lo contrario use un 404.
En mis ejemplos, puedo recorrer una lista vacía sin verificar 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, puede devolver un objeto utilizando el patrón de objeto nulo si se adapta a sus necesidades, pero eso es una discusión para otro hilo.
Me opongo fuertemente a 404 a favor de 204 o 200 con datos vacíos.
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, la clase completa de códigos de error del cliente (4xx) no es adecuada.
Más importante aún, 404 puede suceder por varias razones técnicas. Por ejemplo, la aplicación se desactiva o desinstala temporalmente en el servidor, los problemas de conexión de proxy y otras cosas. 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, inténtelo de nuevo más tarde".
Esto puede ser fatal: imagínese un servicio de contabilidad en su compañía que enumere a todos los empleados que se deben a una bonificación anual. Desafortunadamente, la única vez que se llama devuelve un 404. ¿Eso significa que nadie debe recibir una bonificación, o que la aplicación está actualmente inactiva para una nueva implementación?
-> Para aplicaciones que se preocupan por la calidad de sus datos, 404 por lo tanto es prácticamente un no-go.
Además, muchos marcos de clientes responden a un 404 al lanzar una excepción sin más preguntas. Esto obliga al desarrollador del cliente a capturar esa excepción, a evaluarla y luego a decidir en función de si se debe registrar como un error que es detectado por, por ejemplo, un componente de monitoreo o si se debe ignorar. Eso tampoco me parece bonito.
La única ventaja de 404 sobre 204 es que puede devolver una entidad de respuesta que puede contener alguna información sobre por qué no se encontró el recurso solicitado. Pero si eso realmente es 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 la 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 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 uno podría usar un encabezado de respuesta HTTP para eso.
Sin embargo, preferiría un 204 o 200 con una respuesta vacía. De esta manera, 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 eso".
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 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 para "no se encontraron resultados" es como lanzar una excepción DatabaseConnectionException si una consulta SQL no arrojó resultados. Puede hacer el trabajo, pero hay muchas causas técnicas posibles que producen la misma excepción que luego se confundiría con un resultado válido.
Para resumir o simplificar,
2xx: Datos opcionales: URI bien formado: los criterios no forman parte de URI: si los criterios son opcionales, se pueden especificar en @RequestBody y @RequestParam debería llevar a 2xx. Ejemplo: filtrar por nombre / estado
4xx: Datos esperados: URI no bien estructurado: los criterios son parte de URI: si el criterio es obligatorio y solo puede especificarse en @PathVariable, entonces debería llevar a 4xx. Ejemplo: búsqueda por ID única.
Por lo tanto, para la situación solicitada: "usuarios / 9" sería 4xx (posiblemente 404) Pero para "usuarios? Nombre = superman" debería ser 2xx (posiblemente 204)
Según el post de w3 ,
200 ok
La solicitud ha tenido éxito. La información devuelta con la respuesta depende del método utilizado en la solicitud
202 Aceptado
La solicitud se ha aceptado para su procesamiento, pero el procesamiento no se ha completado.
204 Sin contenido
El servidor ha cumplido con la solicitud pero no necesita devolver un cuerpo de entidad, y puede querer devolver información actualizada.
400 Petición Incorrecta
El servidor no pudo comprender la solicitud debido a una sintaxis mal formada. 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 da ninguna indicación de si la condición es temporal o permanente
Si se espera que el recurso exista, pero podría estar vacío, argumentarí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.
Así que prefiero que / las cosas devuelvan un 200 OK con {"Artículos": []} que un 204 sin nada, porque de esta manera una colección con 0 artículos puede tratarse de la misma manera que una colección con uno o más artículo en él.
Acabo de dejar el 204 No Content for PUTs y DELETEs, en 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.
TL; DR: uso 404
Ver este blog . Lo explica muy bien.
Resumen de los comentarios del blog sobre 204
:
-
204 No Content
no es terriblemente útil como código de respuesta para un navegador (aunque de acuerdo con las especificaciones HTTP, los navegadores necesitan entenderlo como un código de respuesta de "no cambiar la vista"). -
204 No Content
embargo, el204 No Content
es muy útil para los servicios web ajax que pueden querer indicar el éxito sin tener que devolver algo. (Especialmente en casos comoDELETE
oPOST
s que no requieren retroalimentación).
La respuesta, por lo tanto, a su pregunta es usar 404
en su caso. 204
es un código de respuesta especializado que no debe volver a menudo a un navegador en respuesta a un GET
.
Los otros códigos de respuesta que son incluso menos apropiados que 204
y 404
:
-
200
deben devolverse con el cuerpo de lo que hayas conseguido con éxito. No es apropiado cuando la entidad que estás buscando no existe. -
202
se utiliza 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 solicitudGET
. Eso rompe todo tipo de reglas. -
400
se utiliza en respuesta a una solicitud HTTP con formato deficiente (por ejemplo, encabezados http mal formados, segmentos incorrectamente ordenados, etc.). Esto seguramente será manejado por cualquier marco que estés usando. No debería tener que lidiar con esto a menos que esté escribiendo su propio servidor desde cero. Edición : los RFC más nuevos ahora permiten el uso de 400 para solicitudes semánticamente inválidas.
La 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
Yo diría, tampoco es realmente apropiado. Como se ha dicho, p. Ej., Por @anneb, yo también creo que parte de los problemas surgen al usar un código de respuesta HTTP para transportar un estado relacionado con un servicio RESTful. Todo lo que el servicio REST tiene que decir sobre su propio procesamiento debe ser transportado por medio de códigos específicos de REST.
1
Argumentarí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.
Supongamos por un momento la siguiente URL: http://example.com/service/return/test
.
- El caso A es que el servidor está "simplemente buscando el archivo en el sistema de archivos". Si no está presente,
404
es 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 algún otro servicio, por ejemplo, algún tipo de sistema de plantillas. Aquí, el servidor no puede hacer ninguna reclamación sobre la existencia del recurso ya que no sabe nada sobre él (a menos que se lo indique el servicio que lo maneja).
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 debe manejar la solicitud no se está ejecutando o no responde; -
200
contrario, el servidor HTTP puede satisfacer la solicitud, sin importar lo que diga el servicio más adelante; -
400
o404
para indicar que no existe tal servicio (a diferencia de "existe pero sin conexión") 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 usar un código de respuesta HTTP en ningún otro que no se haya dicho antes. 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:EMPTY
por ejemplo, si se le pidió que buscara algo. y esa investigación volvió vacía; -
REST:NOT FOUND
si se solicitó específicamente para algo. “Similar a ID”, 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 fue enviada no es reconocida por el servicio.
(tenga en cuenta que los prefijo con "REST:" con el propósito de marcar el hecho de que, si bien estos pueden tener los mismos valores o palabras que los códigos de respuesta HTTP, son completamente diferentes)
3
Regresemos a la URL anterior e inspeccionemos el caso B donde el servicio indica al servidor HTTP que no maneja esta solicitud en sí, sino que la pasa al SERVICE
. HTTP solo entrega lo que es devuelto por el SERVICE
, no sabe nada acerca de la parte de return/test
ya que está a cargo del SERVICE
. Si ese servicio se está ejecutando, HTTP debería devolver 200
ya que efectivamente 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 realmente se espera:
- si
return/test
solicita un recurso específico: si existe, devuélvalo con el estadoREST:FOUND
; si ese recurso no existe, devuelvaREST:NOT FOUND
; esto podría extenderse para devolverREST:GONE
si sabemos que existió una vez y no volveremos, yREST:MOVED
si sabemos que se ha ido a Hollywood - si
return/test
se considera una operación de búsqueda o de filtro: si el conjunto de resultados está vacío, devuelva un conjunto vacío en el tipo solicitado y un estado deREST:EMPTY
; un conjunto de resultados en el tipo solicitado y un estado deREST:SUCCESS
- si
return/test
no es una operación reconocida porSERVICE
: devolverREST:ERROR
si es completamente incorrecto (por ejemplo, un error tipográfico comoretrun/test
), oREST:NOT IMPLEMENTED
en caso de que se planifique para más adelante.
4
Esta distinción es mucho más limpia que mezclar las dos cosas diferentes. También hará que la depuración sea más fácil 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á hablando". Si bien la parte de REST de mi solicitud puede estar perfectamente bien, estoy buscando par''Mach en todos los lugares equivocados.
- Por otro lado, HTTP 200 y REST: ERR me dice 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 incorrecto: 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 utilizan para denotar el estado de un servicio cuyos resultados son servidos por HTTP, o para denotar algo. Eso no está en el ámbito del propio servidor HTTP. Debido a esta discrepancia, la pregunta no puede ser respondida y todas las opiniones están sujetas a mucha discusión.
El estado de una solicitud procesada por un servicio y no el servidor HTTP REALMENTE NO DEBE (RFC 6919) se debe proporcionar mediante un código de respuesta HTTP. El código HTTP DEBERÍA (RFC 2119) solo contiene información que el servidor HTTP puede proporcionar desde su propio alcance: a saber, si se encontró que el servicio procesaba la solicitud o no.
En su lugar, se DEBE utilizar una forma diferente para informar al consumidor sobre el estado de la solicitud al servicio que en realidad 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.