Cuándo usar el código de estado HTTP 404 en una API

58

Estoy trabajando en un proyecto y después de discutir con la gente en el trabajo durante más de una hora. Decidí saber qué diría la gente en el intercambio de fichas.

Estamos escribiendo una API para un sistema, hay una consulta que debería devolver un árbol de Organización o un árbol de Objetivos.

El árbol de Organización es la organización en la que el usuario está presente. En otras palabras, este árbol siempre debe existir. En la organización, un árbol de meta debe estar siempre presente. (ahí es donde comenzó la discusión). En caso de que el árbol no exista, mi compañero de trabajo decidió que sería correcto responder la respuesta con el código de estado 200. Y luego comenzó a pedirme que arregle mi código porque la aplicación se estaba desmoronando cuando no hay árbol.

Intentaré evitar las llamas y la furia.

Sugerí generar un error 404 cuando no hay árbol. Al menos me dejaría saber que algo está mal. Cuando uso 200, tengo que agregar una verificación especial a mi respuesta en la devolución de llamada exitosa para manejar errores. Espero recibir un objeto, pero en realidad puedo recibir una respuesta vacía porque no se encuentra nada. Suena totalmente justo marcar la respuesta como un 404. Y luego comenzó la guerra y recibí el mensaje de que no entendía el esquema del código de estado HTTP. ¿Entonces estoy aquí y pregunto qué le pasa al 404 en este caso? Incluso recibí el argumento "No encontró nada, así que es correcto devolver 200". Creo que está mal ya que el árbol debe estar siempre presente. Si no encontramos nada y esperamos algo, debería ser un 404.

Más información,

Olvidé agregar las URL que se obtienen.

Organizaciones

/OrgTree/Get

Metas

/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...

Mi error, se requieren ambos parámetros. Si se proporciona cualquier versiónDate que se pueda analizar a una fecha, devolverá la revisión de cierre. Si ingresa algo en el pasado, devolverá la primera revisión. Si por Id con un id que no existe, sospecho que devolverá una respuesta vacía con 200.

Extra

Además, creo que la mejor respuesta al problema es crear objetos predeterminados cuando se crean organizaciones, no tener un árbol no debería ser un caso válido y debería verse como un comportamiento indefinido. No hay forma de que se pueda usar una cuenta sin ambos árboles. Por eso, deben estar siempre presentes.

También me vinculó esto (uno similar pero no puedo encontrarlo)

http://viswaug.files.wordpress.com/2008/11/http-headers-status1.png

Loïc Faure-Lacroix
fuente
Por favor aclare: ¿cómo puede desmoronarse la aplicación cuando no hay árbol, si siempre hay un árbol por condición previa ? (Estoy de acuerdo contigo parece un 404)
Andres F.
Bueno, el código no estaba buscando un nulo, y estaba analizando una cadena json y como un objeto. En algún lugar del código, el objeto que "está" cargado no está presente porque no se puede encontrar internamente.
Loïc Faure-Lacroix
44
Sería más claro si proporciona los URI para el recurso al que está intentando acceder. Si es / metas / devuelves 200 y conjunto vacío. Si está intentando acceder a / goals / {goal_id}, devuelve 404. Si devolvió 404 para solicitar / goals /, significa que el URI ya no existe y ya no debe usarse.
imel96
1
Aún en ambos casos la pregunta es válida. ¿Qué debería /GoalTree/GetById?versionId=CompletelyInvalidIDvolver? No fue un éxito, ya que el recurso nombrado /GoalTree/GetById?versionId=CompletelyInvalidIDliteralmente no se encontró.
2
¡Genial, ahora la discusión ha pasado de tu trabajo a Internet! ¡Es imparable ahora!
Carlos Campderrós

Respuestas:

80

En caso de duda, consulte la documentación . Al revisar las definiciones del W3C para los códigos de estado HTTP, nos da esto:

200 OK: la solicitud se ha realizado correctamente. La información devuelta con la respuesta depende del método utilizado en la solicitud.

404 no encontrado: el servidor no ha encontrado nada que coincida con el URI de solicitud.

En el contexto de su API, depende mucho de cómo se crean las consultas y cómo se recuperan los objetos. Pero, mi interpretación siempre ha sido que:

  • Si solicito un objeto en particular y existe un 200código de retorno , si no existe, devuelve el 404código correcto .
  • Pero, si solicito un conjunto de objetos que coincidan con una consulta, un conjunto nulo es una respuesta válida y quiero que se devuelva con un 200código. La razón de esto es que la consulta fue válida, tuvo éxito y la consulta no devolvió nada.

Entonces, en este caso está en lo correcto , el servicio no está buscando "una cosa específica", está solicitando una cosa en particular, si esa cosa no se encuentra, dígalo claramente.

Creo que Wikipedia lo pone mejor:

200 OK - ... La respuesta real dependerá del método de solicitud utilizado. En una solicitud GET, la respuesta contendrá una entidad correspondiente al recurso solicitado.

404 No encontrado: el recurso solicitado no se pudo encontrar, pero puede estar disponible nuevamente en el futuro. Se permiten solicitudes posteriores del cliente.

Me parece bastante claro.

En cuanto a las solicitudes de ejemplo

/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...

Para el formato, usted dijo, siempre devuelve la revisión más cercana a esa fecha. Nunca devolverá un objeto, por lo que siempre debería estar regresando 200 OK. Incluso si esto fuera capaz de tomar un rango de fechas, y la lógica fuera devolver todos los objetos dentro de ese marco de tiempo devolviendo 200 OK - 0 Los resultados están bien, ya que para eso estaba la solicitud - el conjunto de cosas que cumplían con ese criterio.

Sin embargo, este último es diferente ya que solicita un objeto específico , presumiblemente único, con esa identidad. Volver 200 OKen este caso es incorrecto ya que el recurso solicitado no existe y no se encuentra .

En cuanto a elegir códigos de estado

  • Códigos 2xx Dígale a un UA que hizo lo correcto , la solicitud funcionó. Puede seguir haciendo esto en el futuro.
  • Códigos 3xx Dígale a un UA lo que usted preguntó que probablemente solía funcionar, pero eso está ahora en otro lado En el futuro, la UA podría considerar simplemente ir a la redirección .
  • Códigos 4xx Le dicen a un UA que hizo algo mal , la solicitud que construyó no es adecuada y no debería intentarlo de nuevo, sin al menos alguna modificación.
  • Códigos 5xx Le dicen a un UA que el servidor está roto de alguna manera . Pero bueno, esa consulta podría funcionar en el futuro, por lo que no hay razón para no volver a intentarlo. (a excepción de 501, que es más de un problema 400).

Usted mencionó en un comentario usando un código 5xx, pero su sistema está funcionando. Se le hizo una consulta que no funciona y que necesita comunicarla a la UA. No importa cómo lo cortes, este es territorio 4xx.

Considere un extraterrestre que consulta nuestro sistema solar

Alien: Computadora, por favor dime todos los planetas que habitan los humanos.

Computadora: 1 resultado encontrado. Tierra

Alien: Computadora, cuéntame sobre la Tierra .

Computadora: Tierra - Mayormente inofensiva.

Extranjero: Computadora, cuéntame sobre todos los planetas que habitan los humanos, fuera del cinturón de asteroides.

Computadora: 0 resultados encontrados.

Alien: Computadora, por favor destruye la Tierra.

Computadora: 200 OK.

Alien: Computadora, cuéntame sobre la Tierra .

Computadora: 404 - No encontrado

Alien: Computadora, por favor dime todos los planetas que habitan los humanos.

Computadora: 0 resultados encontrados.

Alien: ¡Victoria para el poderoso Imperio Irken!

Nick Tsai
fuente
44
+1 Esta no es una consulta que no devuelve resultados. Esto es como pedirle al navegador una página web conocida y no encontrarla. Exactamente para qué está el 404.
Andres F.
2
@ imel96 olvida que la cadena de consulta es parte de la URL.
Loïc Faure-Lacroix
1
@LegoStormtroopr Tu divertido ejemplo "alienígena" funciona porque el universo NO es inválido cuando la Tierra no existe. Pero según la explicación del OP, su sistema debe incluir el árbol. Sin árbol, el sistema no funciona.
Andres F.
1
@LegoStormtroopr imagina una tabla de base de datos. Consulta la tabla, a veces obtiene resultados, a veces no. La tabla es su recurso, siempre está ahí, independientemente de que devuelva filas o no. La tabla es identificable, tiene nombre (como los recursos http tienen URI). Las filas no lo son, solo coinciden con algunos parámetros. Incluso en la base de datos, si realiza una actualización que no coincide con nada, obtendrá "Aceptar 0 filas afectadas".
imel96
2
@LegoStormtroopr ya tienes la respuesta. Si quieren reasignar / GoalTree / GetById? VersionId = x, entonces debería devolver 301 con el encabezado de ubicación establecido en / GoalTree / Id / x.
imel96
11

Ignorando el hecho de que / GoalTree / Get * parece un verbo, no recursos, siempre debe devolver 200 porque el URI / GoalTree / Get * representa recursos que siempre están disponibles para el acceso y no es un error del cliente si no hay un árbol como resultado de una solicitud. Simplemente devuelva 200 con un conjunto vacío cuando no haya una entidad que se devolverá.

Utiliza 404 si no se encuentra el recurso, no cuando no hay entidad.

Dicho de otra manera, si desea devolver 404 para sus objetos, entonces dele sus propios URI.

imel96
fuente
1
Hmm Esto tiene sentido. 404 es un error del usuario , pero como explica el OP, en realidad es un error del sistema ; ¡La solicitud del usuario es perfectamente válida! Sin embargo, no estoy de acuerdo con que 200 sea la respuesta correcta, porque "sin árbol" es un error .
Andres F.
@ imel96 Prefiero que siempre se devuelvan entidades válidas en lugar de vacío / código de estado 4xx / 5xx. Si fuera solo yo, devolvería una entidad válida como lo hace un wiki, por ejemplo. Menos dolor de cabeza sin necesidad de manejar errores. Tal como están las cosas, diría que es como un 500. El sistema está en un estado indefinido, no debería suceder. Y regresar bien no tiene sentido. 404 con respecto al rfc tampoco tiene sentido. Entonces, cuando nada tiene sentido ... ¡solo 500 tiene sentido!
Loïc Faure-Lacroix
@Sybiam bien, pediste el código de estado http que está muy bien definido. En este sentido, incluso si su lógica empresarial dice que es un error, no significa que el sistema como un servidor http tenga un error. En su caso, entendió su solicitud, procesó su consulta y simplemente sucedió que el resultado no es una entidad. Por lo tanto, tampoco puede usar 500. Al menos considere darle a sus objetos URI adecuados y ver si el rfc tiene más sentido o no.
imel96
+1 Si tenía una API REST (cada entidad tenía su propia ruta), entonces podría devolver un 404, pero sus rutas son verbos y siempre se encontrarán.
Deja de dañar a Monica el
@OrangeDog: /GoalTree/GetById?versionId=12345 es un URI perfectamente bueno (bueno, uno relativo, al menos) que identifica un recurso específico, es decir, los datos correspondientes a la ID de versión 12345en el sistema. Si no existen datos con tal ID, una respuesta HTTP 404 es perfectamente apropiada. Por supuesto, el cuerpo de la respuesta debe, en cualquier caso, contener una respuesta con el formato adecuado (por ejemplo, JSON, si eso es lo que esperan los clientes que solicitan tales recursos) que indique la naturaleza específica y la causa del error.
Ilmari Karonen
7

Esta es una pregunta interesante, porque se trata de la especificación del sistema.

La respuesta de imel96 me ha convencido de que un 404 no sería una respuesta adecuada, ya que la familia de códigos 4xx es principalmente para errores de usuario / cliente , y este no es uno. La URL está bien formada y el árbol debe estar allí; si no es así, ¡el sistema está en un estado inconsistente!

Por lo tanto, este es un error del servidor , es decir, algo en la familia 5xx. Posiblemente un error genérico del servidor interno 500 o un servicio 503 no disponible (el servicio es "traerme el árbol que debe estar allí").

Andres F.
fuente
2
No es cierto, el usuario está en error porque pidió algo que no existe .
@LegoStormtroopr Pedir algo que no existe no siempre es un error. Si solicita un recurso de red y la red está inactiva, es un error de red .
Andres F.
1
@LegoStormtroopr Además, el árbol debe existir; el sistema no puede funcionar sin él, según la explicación del OP. Por lo tanto, es válido solicitar este recurso; Si no está allí, debe ser un error del sistema (o servidor).
Andres F.
2
@Sybiam Si va a seguir la ruta de un código 5xx, 503 es "503 Servicio no disponible: el servidor actualmente no puede manejar la solicitud debido a una sobrecarga o mantenimiento temporal del servidor". Su servidor no está sobrecargado, no encuentra una solicitud. Además, los códigos 5xx son para cuando "el servidor es consciente de que ha cometido un error o no puede realizar la solicitud"
1
@AndresF. Para ser honesto, un código 500 probablemente esté bien. Dado que la pregunta ha cambiado con el tiempo, funcionaría. Sobre todo, me estoy recuperando de devolver 200 si no todo está bien.
6

Yo diría que un código de respuesta 200 o 404 puede ser válido , dependiendo de cómo se mire la situación.

La cuestión es que los códigos de respuesta HTTP se definen en el contexto de un servidor , que puede entregar varios recursos en función de su URL. En este contexto, los significados de 200 OKy 404 Not Foundson perfectamente inequívocos: el primero dice "aquí está el recurso que solicitó", mientras que el segundo dice "lo siento, no tengo ningún recurso como ese".

Sin embargo, en su situación, tiene una capa de aplicación adicional entre el servidor HTTP y los recursos reales (árboles) que se solicitan. La aplicación ocupa una especie de espacio intermedio que no está bien tratado en la especificación HTTP.

Desde el punto de vista del servidor web, las miradas de aplicación tipo de como un recurso: es típicamente un archivo en el servidor, identificado por (una parte de) la URL, al igual que otros recursos (por ejemplo, archivos estáticos) el servidor puede servir. Por otro lado, es un tipo de recurso extraño, ya que consiste en un código ejecutable que determina dinámicamente el contenido y, de hecho, incluso el código de estado de la respuesta, lo que hace que se comporte de alguna manera más como un mini servidor.

En particular, en su caso de ejemplo, el servidor web puede localizar la aplicación muy bien, pero la aplicación no puede localizar el subrecurso (árbol) que se ha solicitado. Ahora, si considera que la aplicación es solo una extensión del servidor y el subpunto (árbol) es el recurso real, entonces es apropiada una respuesta 404 : el servidor simplemente ha delegado la tarea de encontrar el recurso real en la aplicación , que a su vez no ha podido hacerlo.

Por otro lado, si su punto de vista es que la aplicación es el recurso que se solicita, entonces obviamente el servidor web debería devolver una respuesta 200 ; después de todo, la aplicación fue encontrada y ejecutada correctamente. Obviamente, en este caso, la aplicación debería devolver un cuerpo de respuesta válido en el formato esperado, indicando (usando cualquier protocolo de nivel superior que codifique el formato) que no se encontraron datos reales que coincidan con la consulta.

Ambos puntos de vista pueden tener sentido. En la mayoría de los casos , al menos para las aplicaciones destinadas a acceder directamente a través de HTTP con un navegador web común, preferiría la vista anterior : al usuario generalmente no le importan los detalles internos como la diferencia entre el servidor y la aplicación, simplemente preocuparse por si los datos que querían están allí o no.

Sin embargo, en el caso específico de una aplicación diseñada para comunicarse con otros programas de computadora usando un protocolo API de alto nivel personalizado, usando HTTP solo como una capa de transporte de bajo nivel , hay un argumento a favor de esta última vista : para clientes que interactúan con una aplicación de este tipo, todo lo que realmente les importa, a nivel HTTP , es si lograron contactar con éxito la aplicación o no. Todo lo demás, en tales casos, a menudo se comunica de forma más natural utilizando el protocolo de nivel superior.


En cualquier caso, independientemente de cuál de las vistas anteriores prefiera, hay algunos detalles que debe tener en cuenta. Una es que, en muchos casos, puede haber una distinción significativa entre un recurso (esencialmente) vacío y uno inexistente .

En el nivel HTTP, un recurso vacío simplemente se indicaría con un código de respuesta 200 y un cuerpo de respuesta vacío, mientras que un recurso inexistente se indicaría con una respuesta 404 y un cuerpo de recurso explicando la ausencia del recurso. En un protocolo API de nivel superior, uno normalmente indicaría un recurso inexistente mediante una respuesta de error, que contiene un código / mensaje de error específico de protocolo adecuado, mientras que una respuesta vacía simplemente sería una estructura de respuesta normal sin elementos de datos.

(Tenga en cuenta que un recurso no necesita tener literalmente cero bytes de longitud para estar "vacío" en el sentido que quiero decir más arriba. Por ejemplo, un resultado de búsqueda sin elementos coincidentes contaría como vacío en sentido amplio, como lo haría un resultado de consulta SQL con sin filas o un documento XML que no contenga datos reales).

También, por supuesto, si la aplicación realmente cree que el subrecurso solicitada debería estar allí, pero no lo encuentra, entonces existe un tercer código de respuesta posible: 500 Internal Server Error. Tal respuesta tiene sentido si la existencia del recurso es una condición previa asumida para la aplicación, de modo que su ausencia indica necesariamente un mal funcionamiento interno.

Finalmente, siempre debes tener en cuenta la ley de Postel :

" Sea conservador en lo que envía y liberal en lo que recibe " .

Si el servidor debe responder en una situación particular con un 200 o un 404 respuesta, eso no es excusa que como el cliente implementador de la manipulación, ya sea la respuesta apropiada y de la manera que maximiza la interoperabilidad robusta. Por supuesto, se puede argumentar qué significa el manejo "apropiado" en diferentes situaciones, pero ciertamente no debería incluir normalmente la caída o "desmoronamiento".

Ilmari Karonen
fuente
El dilema bien explicado.
Marcel
No hay dilema. esta respuesta no se basa en qué recurso se define como en el rfc relacionado. ver mi comentario en respuesta @LegoStormtroopr.
imel96
@ imel96: Creo que está malinterpretando RFC 1630: el párrafo que cita en su comentario anterior se lee en su totalidad: "El signo de interrogación ("? ", ASCII 3F hexadecimal) se utiliza para delimitar el límite entre el URI de un consultable objeto y un conjunto de palabras utilizadas para expresar una consulta sobre ese objeto. Cuando se utiliza este formulario, el URI combinado representa el objeto que resulta de la consulta que se aplica al objeto original. " (énfasis mío). Por lo tanto, está claro que la cadena de consulta es de hecho parte del URI (aunque la parte anterior a la cadena de consulta es, necesariamente, también un URI válido por sí mismo) ...
Ilmari Karonen
... y que este URI combinado identifica un recurso específico que el cliente puede solicitar enviando ese URI al servidor. En cualquier caso, RFC 2616 (HTTP) simplemente define un recurso como "Un objeto o servicio de datos de red que puede ser identificado por un URI, como se define en la sección 3.2". y continúa diciendo que "en lo que respecta a HTTP, los identificadores uniformes de recursos son simplemente cadenas formateadas que identifican, por nombre, ubicación o cualquier otra característica, un recurso".
Ilmari Karonen
@IlmariKaronen tienes razón. Confundí HTTP con REST. Sin embargo, todavía no parece correcto porque no estoy seguro de qué puede hacer con un recurso con URI como / GoalTree / Get? VersionDate = 2000BC
imel96
3

¿Qué tal un 204 Sin contenido? Sugeriría que su solicitud se procesó correctamente pero no devuelve nada. Todavía es un "éxito", pero le permite ver si tiene resultados basados ​​únicamente en el código de estado.

modernserf
fuente
66
si sigue leyendo la especificación, "Esta respuesta está destinada principalmente a permitir la entrada de acciones para que tengan lugar sin causar un cambio en la vista de documento activa del agente de usuario". Por lo tanto, no debe usarse para solicitudes GET.
imel96
3

Si la URL representa un recurso que nunca existió, devuelva 404 No encontrado

Si la URL representa un recurso que es una lista vacía, devuelva una lista vacía y 200 OK.

Ejemplo:

{
  total: 0,
  items: []
}

Si la URL representa un recurso que solía existir, devuelve 410 Gone.

Con respecto al diálogo de Lego Stormtrooper:

Alien: Computer, please tell me all planets that humans inhabit. GET /planets?inhabitedBy=humans

Computer: 200 OK. { total: 1, items:[{name:'Earth'}] }

Alien: Computer, please tell me about Earth. GET /planets/earth

Computer: 200 OK. {name:'Earth', status: 'Mostly Harmless'}

Alien: Computer, please tell me about all planets humans inhabit, outside the asteroid belt. GET /planets?inhabitedBy=humans&distanceFromSun=lots

Computer: 200 OK. {total:0, items:[] }

Alien: Computer, please destroy Earth. DELETE /planets/earth

Computer: 204 No Content. (or 202 Accepted if it takes some time to destroy Earth)

Alien: Computer, please tell me about Earth. GET /planets/earth

Computer: 410 Gone

Alien: Computer, please tell me all planets that humans inhabit. GET /planets?inhabitedBy=humans

Computer: 200 OK 0 {total: 0, items:[] }

Alien: Victory for the mighty Irken Empire!
Neil McGuigan
fuente
1

Por lo que parece, esta es una API para uso interno . Esto ofrece la ventaja de utilizar el esquema que ofrezca el mayor beneficio , independientemente de si se trata de un libro (especificación) o no. Esto no significa inventar completamente sus propios códigos de estado, pero está bien 'doblar' un poco las reglas si es beneficioso.

Estoy de acuerdo con su soporte en que debe obtener un código de estado que muestre que algo salió mal. Esto es, después de todo, para qué sirven los códigos de estado. También obtienes el beneficio de bibliotecas que lanzan excepciones / etc. en código de estado no 200 para que no tenga que verificar explícitamente (o puede escribir su propio contenedor que haga esto).

También estoy de acuerdo con el punto de vista de Andrés F. de que 500 es apropiado ya que el árbol debería existir. Sin embargo, en la práctica, me gusta dividir los errores del servidor en dos categorías. Algo inesperado salió mal y algo que prácticamente puedo verificar salió mal. Esto da como resultado los siguientes códigos de estado,

  • 200 - Todo está bien
  • 404 - URL incorrecta
  • 409 - Algo salió mal
  • 500 - Se produjo un error inesperado en el servidor

En su caso particular, puede verificar si el árbol existe o no en el lado del servidor y, si no está allí, devolver un 409. Es un error esperado (sabe que puede suceder, puede verificarlo, etc.) . El conflicto 409 es solo mi preferencia personal, un 5xx también puede ser apropiado siempre que pueda sentarse y decidir esto con su equipo.

La categorización de códigos como este lo ayuda a identificar más rápidamente el tipo de error, pero puede tener beneficios más allá de la organización. A menudo, con los errores del sitio web, no desea que el cliente reciba errores inesperados, ya que esto puede ser un problema de seguridad y revelar vulnerabilidades, por lo que devuelve un 500 genérico "Se produjo un error". y registre el error completo en el servidor. Pero si se produce un error esperado como 409, sabe que sería seguro mostrar el error al cliente y no tiene que dejarlo en la oscuridad en cuanto a lo que sucedió. Este es solo un uso práctico que puedo contar, pero hay muchas posibilidades.

Esto es un poco complicado porque estás publicando esto porque no puedes estar de acuerdo con tus compañeros de trabajo, pero parece que ustedes están discutiendo más sobre la semántica y quién es políticamente correcto. Realmente no importa quién sea más adecuado, siempre y cuando pueda idear un sistema que beneficie más a la empresa.

Por otro lado, si esta es una API pública, seguir las especificaciones lo más cerca posible sería más importante para evitar confusiones entre la comunidad.

Despertar
fuente
0

Tomando una puñalada tangencial a esto: si un humano finalmente está utilizando la API (a través de una GUI), sugeriría hacer lo que sea que haga la vida más fácil para el usuario final. La inexistencia del árbol cuando debería existir es un error de "inconsistencia del modelo de dominio". Un error del sistema es cuando se quedó sin memoria o tuvo alguna otra falla sistémica. Entonces devolver 5xx es inapropiado. Como mencionan varias personas anteriormente, 4xx podría ser apropiado si el árbol en sí tuviera su propio URI, que no es el caso aquí. Pero esto es lo que 404 le dice al cliente: puede intentarlo una y otra vez hasta que recupere algo. Si devolvió 200, podría devolver suficientes diagnósticos al usuario o agente de usuario para que el agente de usuario pueda mostrar una medición para que el usuario deje de volver a intentarlo y solo contacte al soporte. Por otro lado, si esta API está destinada solo a sistemas,

usuario90766
fuente
Todo lo que 404 realmente dice es "esa cosa no está aquí, y no sé dónde está". 3xx y 5xx están bien para volver a intentarlo. Pero 4xx dice: "su consulta actual fue insuficiente para que yo encuentre algo para usted. Por favor, vaya".
Me gusta la posibilidad de distinguir entre URL NO ENCONTRADA y Recurso NO ENCONTRADO ... Por lo tanto, el Punto final de servicio está en funcionamiento 200, sin embargo, el recurso solicitado NO SE ENCUENTRA 404 (Cuerpo de respuesta).
Limonada