Estoy trabajando con una API REST que reside en un servidor que maneja datos para una multitud de dispositivos IoT.
Mi tarea es consultar al servidor utilizando la API para recopilar información de rendimiento específica sobre dichos dispositivos.
En un caso, obtengo una lista de dispositivos disponibles y sus identificadores correspondientes, luego consulto al servidor para obtener más detalles utilizando esos identificadores (GUID).
El servidor está devolviendo una 500 Internal Server Error
consulta sobre uno de esos ID. En mi aplicación, se produce una excepción y no veo detalles sobre el error. Si examino la respuesta más de cerca con Postman , puedo ver que el servidor devolvió JSON en el cuerpo que contiene:
errorMessage: "This ID does not exist"
.
Para empezar, ignore el hecho de que el servidor proporcionó la ID; ese es un problema separado para el desarrollador.
¿Debería una API REST devolver a 500 Internal Server Error
para informar que una consulta hace referencia a un objeto que no existe? En mi opinión, los códigos de respuesta HTTP deberían referirse estrictamente al estado de la llamada REST, más que a la mecánica interna de la API. Esperaría un 200 OK
con la respuesta que contiene el error y la descripción, que sería propiedad de la API en cuestión.
Se me ocurre que hay una diferencia potencial en las expectativas dependiendo de cómo se estructura la llamada REST.
Considere estos ejemplos:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
En el primer caso, la ID del dispositivo se pasa como una variable GET. Un 404 o 500 indicaría que la ruta ( /restapi/deviceinfo
) no se encuentra o da como resultado un error del servidor.
En el segundo caso, la ID del dispositivo es parte de la URL. Sería más comprensivo de a 404 Not Found
, pero aún podría argumentar en función de qué partes de la ruta se interpretan como variables frente a puntos finales.
fuente
Respuestas:
Creo que una respuesta 404 es la mejor coincidencia semántica aquí, porque no se encontró el recurso que estaba tratando de encontrar (como lo representa el URI utilizado para la consulta). Devolver una carga de error en el cuerpo es razonable, pero no es obligatorio.
De acuerdo con RFC 2616 , la definición del código de estado 404 es:
fuente
/questions
, es/questions/368213
. Ese punto final no existe en su escenario. Piénselo de esta manera: si realiza un GET en / foo / bar y no hay barra, ¿por qué la respuesta debería ser diferente si / foo existe o no?How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?
- 400 Solicitud incorrecta.Usaré tus ejemplos.
Si el punto final devuelve una matriz json , la mejor opción es
200 OK
con una matriz vacía si no se encuentra ningún resultado.Si el punto final está diseñado para devolver un único resultado , mi elección sería
404 NOT FOUND
, pues, para mí, la sintaxis correcta para este tipo de punto final es:http://example.com/restapi/deviceinfo/123
. Usualmente uso request param solo para filtrar y cuando mi punto final devuelve una matriz.Creo que esta pregunta ya fue respondida aquí . POST o GET, la mejor opción parece
404 NOT FOUND
porque123
no se encontró el recurso .En ambos casos, no puedo ver la necesidad de explicar la razón por la cual la solicitud no se completó. La información de solicitud y el código HTTP ya explican por qué.
fuente
/itms/1234
o no/items/12234
.HTTP 404
es correcto, porque el servidor entiende qué recurso está pidiendo el cliente, pero no tiene ese recurso.El hecho de que esté trabajando con una "API REST" es la clave. La API debería comportarse como si estuviera realizando una Transferencia de estado REpresentacional, no ejecutando una función. (Claro, el término "REST" ha llegado a tener un significado más amplio, pero aún puede usar su significado literal con buenos resultados aquí.) El cliente ha pedido el estado de un recurso descrito por la URL
http://example.com/restapi/device/123/info
. Una cadena de consulta (/deviceinfo?id=123
) no cambiaría la situación. El servidor sabe que está solicitando transferir el estado del dispositivo 123, pero no lo reconoce como un recurso conocido. Por lo tantoHTTP 404
.Las otras posibles respuestas discutidas aquí también tienen significados específicos:
HTTP 200
- Tenemos el estado para ti; está en el cuerpo de respuesta.HTTP 204
- Tenemos el estado para ti; Está en blanco.HTTP 400
- No podemos decir qué recurso está preguntando. Repara tu URL.HTTP 500
- Funcionamos mal. No es tu culpa.Ver RFC 2616 Sec. 10 según corresponda.
fuente
Un error 5xx se usa generalmente para indicar que el servidor encontró un error y no puede completar la solicitud. Si el servidor toma la solicitud, puede analizarla con éxito y luego hace su trabajo, eso no debería devolver un error 5xx.
No estoy seguro de si hay algún tipo de convención sobre qué devolver si una consulta no produce resultados. He visto tanto lo que usted describe (un 200 con un cuerpo que contiene un mensaje) como un 404 que indica que no se encontraron resultados. El 200 probablemente tiene más sentido: la solicitud se completó con éxito y no hubo problemas con la solicitud del cliente o durante el proceso del servidor. Un cuerpo puede entregar un mensaje al cliente.
Trataría ambos ejemplos (
http://example.com/restapi/deviceinfo?id=123
yhttp://example.com/restapi/device/123/info
) de la misma manera:123
es un parámetro. Ambos casos son diferentes formas de estructurar una solicitud para obtener información del dispositivo para un dispositivo con ID 123.Primero, consideraría la autorización y autenticación. Si el usuario no tiene los permisos apropiados, devolvería un 403 o un 401 según corresponda. Aunque se llama "No autorizado", entiendo que 401 se trata más de autenticación y 403 se trata de no autorizado o permiso denegado. Sin embargo, no sería demasiado exigente aquí si solo quisieras apegarte a 403 para todos los errores de autenticación y autorización.
Entonces, me ocuparía de la identificación. Según su ejemplo, parece que es una identificación numérica. Si se proporcionara un valor no numérico, devolvería un 400. Si el parámetro pudiera ser un identificador de dispositivo válido, entonces continuaría con el procesamiento. Si hubiera otros argumentos, también se comprobarían aquí. Esperaría que el cuerpo de respuesta contenga información apropiada sobre por qué la solicitud fue incorrecta.
Si todos los parámetros fueran válidos, comenzaría a procesar la solicitud. Si el sistema o cualquier dependencia (una base de datos, un servicio de terceros, otro servicio interno) no está disponible, devolvería un código 5xx: 503 sería específico, pero un 500 también sería aceptable. En cualquier caso, devolvería un cuerpo con detalles adicionales. Tenga en cuenta que si una dependencia externa informa un Tiempo de espera de solicitud 408, me comería eso y devolvería un 500 a mi cliente, permitiendo que un cliente reciba un 408 solo si la solicitud a mi sistema expiró. Si el sistema puede completar la solicitud, devolvería un 200 y el cuerpo apropiado.
204 puede ser útil en algunos casos, pero le impide enviar un cuerpo de respuesta. Especialmente en una configuración de API, enviar un cuerpo de respuesta con información que se puede alimentar a un mecanismo de registro o informe parece ser la decisión correcta en la mayoría de los casos.
La única vez que se devolvería un 404 es si el servidor no tenía un
/deviceinfo
punto final o un/device/:id/info
punto final.No consideraría que una identificación que no se encuentre sea la misma que el recurso no encontrado. El recurso es la información del dispositivo para un dispositivo en particular (en su ejemplo). Devolver un 404 significaría que el recurso (la información del dispositivo) no existe. Un 200 con un cuerpo apropiado significa que el sistema puede proporcionar información del dispositivo. Puede o no haber un dispositivo con la ID especificada.
fuente
device: 123; status: not found;
. Entonces sé que la consulta funcionó y que la API me está dando información útil.Un error HTTP de la serie 500 indica un mal funcionamiento del servidor. Además de
501 Not Implemented
y505 HTTP Version Not Supported
, el uso de estos códigos de error implica que volver a intentar la solicitud en un momento posterior puede tener éxito (aunque solo503 Service Unavailable
lo declara explícitamente). Idealmente, un servidor nunca debería producir uno de estos códigos, aunque la incapacidad para escribir software libre de errores y aprovisionar el servidor con recursos infinitos significa que los necesitará de vez en cuando.Para un resultado de "objeto no existe", probablemente debería devolver
404 Not Found
(cuando la solicitud es para un objeto por nombre) o200 Success
con un cuerpo de resultado vacío (cuando busca un objeto por atributos).204 No Content
parece tentador, pero lo usaría solo para situaciones donde la falta de un cuerpo de respuesta es el resultado esperado.fuente
Como cliente de su API, cuando realizo cualquiera de estas llamadas:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
Espero recuperar una (representación de) un
DeviceInfo
objeto (o algún tipo particular de todos modos, ya sea un tipo formal o simplemente algo conforme a una convención documentada de "tipo de pato"). Quiero que un200
estado signifique que realmente tengo uno, y puedo seguir adelante y usarlo.Para las API REST, pienso en los códigos de estado 400 y 500 como excepciones. Los utiliza para indicar cuándo no puede devolver una respuesta "normal" a la solicitud que ha recibido, por lo que el cliente deberá hacer algo excepcional en lugar de procesar la información que esperaba recuperar.
Esto significa, como consumidor de API, que puedo usar algún tipo de función de llamada de descanso comprobado que recupera una respuesta o arroja una excepción. Eso es genial; mi lógica normal puede ser un código de línea recta, y puedo organizar mi manejo de errores de la misma manera que lo hago en el código local. Los 404 inesperados se manifestarán como excepciones de "no se encontraron recursos" sin que tenga que hacer nada en absoluto, no como errores de "atributo faltante" cuando más tarde procese
{ errorMessage: "Device 123 not found" }
como si fuera unDeviceInfo
objeto.Si razona que
http://example.com/restapi/deviceinfo
se encuentra el punto final , y es solo elid=123
que no, y devuelve 200 con un mensaje de error en el cuerpo, entonces está creando exactamente el mismo tipo de problemas de interfaz que las funciones C que podrían devolver un resultado correcto o un código de error, o métodos que indican problemas al devolver arbitrariamentenull
. Es mucho mejor como usuario de su interfaz que los errores se indiquen a través de un canal "separado" de los retornos regulares. Eso también se aplica aquí, a pesar de que las respuestas HTTP 200, 404 y 500 son el mismo canal desde un punto de vista de bajo nivel. Están estandarizados y son fáciles de distinguir, por lo que mi marco de cliente REST puede activar fácilmente esos estados para convertirlos en las estructuras adecuadas en mi idioma; para hacer lo mismo con la capa JSON (donde siempre dice 200 y me daDeviceInfo
un mensaje de error o un mensaje de error) Necesito incorporar algunos conocimientos de los esquemas JSON que usa.Por lo tanto, solo use 200 cuando pueda devolver un valor válido del tipo esperado (es por eso que
http://example.com/restapi/search-devices?colour=blue
puede devolver 200 con una matriz vacía si no hay dispositivos azules; una matriz vacía es una matriz válida y una respuesta sensata a la solicitud "I quisiera los detalles de todos los dispositivos azules "). Si no puede, use el código de estado no 200 más apropiado. A pesar de que "el dispositivo 123 no existe" es la respuesta correcta a "darme los detalles del dispositivo 123", y no es un error para el servidor , es una excepción para la expectativa del cliente de que volveráDeviceInfo
y debería no se comunicará como una respuesta normal de "aquí está lo que pidió".fuente
Podría usar el error 422 Entidad no procesable para diferenciar de 404 no encontrado . 422 significa que el servidor comprende la solicitud pero no puede dar una respuesta adecuada. Estoy usando este código en situaciones similares.
fuente
El error 500 normalmente indica que la solicitud bloqueó un programa del lado del servidor; En entornos empresariales, estos errores se tratan como un huevo en la cara y se evitan.
El error 4xx debe indicarle al programador que el punto final API (recurso) no existe. En consecuencia, una vez que se alcanza el punto final apropiado, cualquier manejo de errores desde ese punto en adelante es responsabilidad del programador de la API que debe manejarse con gracia, es decir, con un mensaje de error de una respuesta 200.
fuente
Aunque el w3 señala que 404 se usa cuando no se aplica ninguna otra respuesta , ¿no sería esto para lo que sirve una respuesta 204 (Sin contenido)? La solicitud fue válida desde el punto de vista del procesamiento y el servidor procesó la solicitud y tiene un resultado. Eso es un éxito, que se inclina hacia las respuestas 2xx. No hubo contenido para esta solicitud en particular, por lo que 204 le dice al usuario que no hubo nada malo en su consulta, pero que no hay nada allí.
También podría hacer un caso débil de que 409 (Conflicto) es una respuesta apropiada. Aunque 409 se usa con mayor frecuencia para una POST, sí dice
podría decirse que la no existencia de la identificación solicitada es el conflicto aquí, y devolver el mensaje de que dicha identificación no existe en el sistema es suficiente información para que el usuario reconozca y solucione el conflicto.
fuente
Las otras respuestas lo cubren, pero solo quería señalar que un error de la serie 500 significa "Me equivoqué". En este caso, "I" significa la API, por lo que se trata de un error del servidor no controlado o similar. Un error de la serie 400 significa "te equivocaste": la persona que llamó a la API envió algo incorrecto.
fuente
Otros usuarios han proporcionado respuestas válidas sobre qué hacer si desea seguir el libro.
Sin embargo, sugeriría que esté leyendo demasiado sobre RESTfulness y que sea absolutamente kosher con respecto a él.
REST es un protocolo caprichoso, porque si quieres seguir el libro mientras lo usas, obliga a que tanto el cliente como el servidor se construyan teniendo un conocimiento específico del hecho de que se están comunicando a través de REST, por lo que, en esencia, el protocolo de comunicación específico es usado no se puede extraer.
Hay un enfoque diferente: evitar por completo RESTfulness, y usarlo solo como un protocolo de comunicación y nada más. Esto significa que las únicas respuestas que deben devolverse son "HTTP 200 OK" y "HTTP 500 Internal Server Error" porque, en lo que respecta al protocolo de comunicación, cualquier intento de comunicación solo puede tener dos resultados: la solicitud fue exitosa entregado al servidor, o no.
Lo que sucede después de la entrega no es asunto del protocolo de comunicación. Por lo tanto, una vez que el servidor ha recibido la solicitud con éxito y comienza a procesarla, pueden producirse muchos errores, pero todos estos son errores específicos de la aplicación que no es asunto del protocolo de comunicación. Deben comunicarse dentro de la carga útil de una respuesta que parece perfectamente exitosa hasta donde el protocolo de comunicación lo sabe.
Entonces, la conclusión es que recomendaría devolver un "HTTP 200 OK" y dentro de la carga útil de respuesta ("cuerpo de contenido de respuesta" en lenguaje HTTP) tener un código de error específico de la aplicación que dice "ID no encontrado" o lo que sea.
fuente