¿Debería "No hay resultados" ser un error en una respuesta REST?

44

Describiré un ejemplo:
Comienzo a hacer un API para una panadería. El API permitirá a las personas buscar en sus catálogos productos para hornear, como las galletas de menta de chocolate caseras hechas con api.examplebakery.com/search?q=..... .

Alguien usa esto para buscar un producto llamado pineapple-banana flavoured cookies y obviamente no encontrará ningún resultado.

¿Debería devolverse esto como un error? La búsqueda no falló, la API buscó y concluyó con éxito que no se pudieron encontrar cookies. La API no debe devolver 404 , porque se encontró la API.

    
pregunta Berry M. 28.09.2017 - 12:47

6 respuestas

115

Cuando hay resultados, la salida es una lista (JSON, basada en su comentario). Para consultas sin resultados, la salida debe ser exactamente la misma. La lista simple tiene 0 elementos en ella.

Entonces, si tu respuesta es normalmente esta:

{
    "results": [
        {
            "name": "Pancakes",
            ....
        },
        {
            "name": "French Fries",
            ....
        }
    ]
}

Luego, para una consulta con 0 resultados, debería ser esto:

{
    "results": []
}

Si también incluye metadatos acerca de cuántas "páginas" de resultados hay, enlaces a esas "páginas", etc., entonces sugiero que diga que hay 1 "página".

El estado HTTP debe ser el mismo que cuando hay resultados - 200 OK .

204 No Content también puede parecer una opción, pero no es porque de hecho esté devolviendo "contenido": la lista vacía. Si cree que una lista vacía no cuenta como "contenido", ¿qué sucede si luego modifica la respuesta para ofrecer sugerencias de ortografía? El núcleo de la respuesta seguirá siendo una lista vacía, pero ahora hay aún más "contenido".

Para obtener más información útil sobre los códigos de estado HTTP, jpmc26 su respuesta vale la pena leerla.

    
respondido por el Jory Geerts 28.09.2017 - 13:07
36

Al decidir sobre un código HTTP, siempre debe hacer esta pregunta:

  

¿Qué puede / hará / debería hacer cualquier cliente arbitrario con la respuesta?

  1. ¿Debe el cliente siempre tratar la respuesta como un error? Entonces desea 4xx o 5xx, dependiendo de si el problema es la entrada del cliente o los procesos del servidor.
  2. ¿Debería el cliente realizar una solicitud en otro lugar? Entonces 3xx es para ti.
  3. ¿El servidor hizo lo que el cliente le pidió (tuvo éxito)? Eso es 2xx.

Siempre decida en qué rango debe estar su código de respuesta primero. Al hacerlo, se eliminan rápidamente muchos códigos de respuesta como opciones y, lo que es más importante, hace que el seguimiento de la semántica de los códigos sea mucho más sencillo. Consulte las secciones iniciales de la documentación del código HTTP para obtener una explicación de lo que representa cada categoría de códigos.

En este caso, el cliente solicitó una lista de resultados dado un filtro de un punto final válido y existente y tiene autorización para acceder a él. El servidor pudo procesar la solicitud y determinar los datos apropiados para devolver (sin elementos), por lo que la solicitud fue exitosa. Simplemente sucede que el filtro que dieron filtró todos los resultados. No le corresponde al servidor determinar si esto es lo que el cliente quería o no, ya que este puede ser un resultado esperado para algunos clientes. Si de alguna manera es un problema para el código del cliente, es responsabilidad del cliente determinarlo, verificarlo y manejarlo adecuadamente. Así que esto es claramente 2xx.

Ahora la pregunta es: "¿Cuál 2xx?" Esto depende de cómo pretenda que responda el servidor.

  • ¿Volverá a enviar una representación de una lista vacía, como algunas otras respuestas describen? Si es así, desea 200. 200 significa que el servidor no experimentó problemas y tiene una representación de los resultados para que el cliente los consuma. Esta es probablemente la forma más conveniente de responder para sus consumidores, que pueden analizar la respuesta ya sea que haya resultados o no y luego averiguar cómo manejar una lista vacía ellos mismos.
  • 204 no está semánticamente mal aquí, pero tendrías que responder con ningún cuerpo del mensaje . Esto significa que todo el código del cliente tendría que verificar explícitamente los diferentes códigos HTTP (o al menos por la falta de un cuerpo del mensaje) y manejarlos por separado. Es inconveniente y es más probable que conduzca a clientes con mal comportamiento.

Los demás no son aplicables en absoluto:

  • 201 está fuera de discusión. No creó ningún recurso persistente y no está devolviendo una ubicación a un recurso creado.
  • 202 está fuera de discusión. La solicitud está hecha; no se está procesando en segundo plano.
  • 203 significa que la respuesta se modificó entre el servidor autorizado y el cliente. Su interfaz REST es el servidor autorizado, por lo que esto no se aplica aquí.
  • 205 no tiene sentido. No necesita que el cliente borre o actualice nada.
  • 206 parece estar diseñado para devolver un recurso grande en múltiples respuestas. También requiere que el cliente solicite una parte del contenido en los encabezados (por lo que la paginación a través de cadenas de consulta no califica). No aplicable aquí.

Por lo tanto, debería ser 200 o 204, y es más probable que 200 conduzca a un código de cliente más simple y sólido (especialmente si utiliza una estructura de respuesta consistente que contenga una lista vacía).

    
respondido por el jpmc26 29.09.2017 - 02:46
15

No. el uso de 404 para indicar que "su consulta se procesó pero no hubo coincidencias" es horrible porque:

  • flujo condicional basado en el manejo de excepciones (es decir, forzar un resultado no excepcional para crear y manejar una excepción en el cliente que puede ser poco productivo e incómodo)

  • no se encuentra la ambigüedad entre la página 'real', usted escribió los errores incorrectos del punto final

Lo que hay que recordar es que siempre hay un cliente para deserializar el mensaje y lo que ese cliente devuelve es importante; no la serialización.

Si el cliente debe devolver nulo, use la serialización de nulo. Si el cliente debe devolver una matriz vacía, use [], si el cliente debe lanzar un error, use 500 y pase el mensaje de error

    
respondido por el Ewan 28.09.2017 - 17:54
9

Muy buena respuesta de Beyond @ Ewan:

Si la consulta es del tipo que devuelve un conjunto de resultados, entonces el conjunto vacío es lógicamente tan apropiado como un conjunto de uno, o un conjunto de más. En general, por las razones que indica @Ewan, hace más daño que bien alterar el conjunto vacío en un error y, simplemente, es innecesario.

Si la consulta es del tipo que busca y devuelve un singleton específico (que se espera encontrar, por ejemplo, coincidencia exacta por id), entonces no se encuentra es una posible respuesta lógicamente apropiada.

    
respondido por el Erik Eidt 28.09.2017 - 18:06
5

Está asumiendo que el código debe realizar una acción especial cuando no se devuelven datos, pero puede que ese no sea el caso. El código podría simplemente estar buscando un recuento de productos, o agregar los resultados a una lista o cualquier otra cantidad de cosas. Solo debe dar un "error" a un usuario si realmente hay un error.

    
respondido por el John Smith 28.09.2017 - 22:44
0

Cuando uso una API, como cliente tengo que manejar casos "exitosos" diferentes de casos "error"; No tengo elección allí. Por lo tanto, debe devolver un error en las situaciones que el cliente quiere para tratar de manera diferente, y el éxito en las situaciones que el cliente quiere para tratar de la misma manera.

Si hago una consulta que podría en teoría devolver cualquier número de resultados, cero, uno, doscientos, etc., entonces deberías devolver "éxito" cada vez que la API entregue la lista completa de todos los resultados. Y posiblemente en los casos en que haya muchos resultados, haya devuelto una lista parcial de resultados para evitar un tamaño excesivo, y existe una forma acordada sobre cómo obtendría los otros resultados. Eso es porque como cliente, a menudo quiero manejar el caso de cero resultados, como el caso de más resultados. Podría tratarlo de manera diferente, pero no quiero que me obliguen a hacerlo.

Es diferente en el caso de que busque un valor. Espero exactamente un resultado, el valor que estoy buscando. Y necesito ese único resultado para continuar lo que quiero hacer de una manera significativa. Aquí es mucho más aceptable devolver un estado 404 para el caso de que no haya ningún valor, porque de todos modos tengo que manejar ese caso de manera diferente.

Resumen: si el cliente espera cualquier cantidad de resultados, de cero a números grandes, devuelva "éxito" si se entregan todos los resultados, incluso si el número es cero. Si el cliente espera exactamente un resultado, devuelva el éxito si se encuentra el resultado, y un error si no se encuentra el resultado.

    
respondido por el gnasher729 02.10.2017 - 19:55

Lea otras preguntas en las etiquetas