¿Cómo elijo un código de estado HTTP en la API REST para "Todavía no está listo, intente nuevamente más tarde"? [cerrado]

152

Estoy desarrollando una API RESTful en la que http://server/thingyapi/thingyblob/1234devuelve el archivo (también conocido como "blob") asociado con la cosa # 1234 para descargar. Pero puede ser que la solicitud se realice en un momento en que el archivo no exista en el servidor, pero definitivamente estará disponible en un momento posterior. Hay un proceso por lotes en el servidor que genera todos los blobs para todas las cositas. Thingy 1234 ya existe y sus datos, además del blob, ya están disponibles. El servidor todavía no ha podido generar el blob 1234 de cositas.

No quiero devolver 404; eso es para cosas que no existen. Esta es una cosita que existe, pero su blob aún no se ha generado. Como un video de YouTube que está "procesando". Tampoco creo que los códigos de redireccionamiento sean adecuados; no hay "otra" URL para probar.

¿Cuál es el código de estado HTTP correcto para devolver en tal caso?

JCCyC
fuente
3
Algo relacionado
Rob Hruska
77
Primero, si la cosa 1234 aún no tiene ninguna representación compatible con GET, ¿en qué sentido existe como un recurso (desde la perspectiva del cliente)? El hecho de que, interno al servidor hay un trabajo en cola para crear 1234, no parece implicar que el recurso 1234 existe. Segundo, ¿de dónde obtuvo el cliente el URI ... / thingyblob / 1234? El servidor probablemente no debería haber proporcionado ese URI al cliente hasta que el recurso fuera realmente GET.
Andy Dennie
1
Una cosita tiene otras propiedades que vale la pena obtener además de la burbuja. Es solo el blob que lleva tiempo generarlo. El cliente los obtiene, por ejemplo, server / thingyapi / thingy / 1234
JCCyC
10
El estándar HTTP proporciona orientación sobre qué códigos de estado usar para qué situaciones. Por lo tanto, esta pregunta no se basa principalmente en la opinión .
Raedwald
2
¿Qué tal 204"Sin contenido"? Esto indica que el servidor ha procesado correctamente la solicitud y no está devolviendo ningún contenido [en este momento].
Timo

Respuestas:

77

Sugiero 202 - Accepted. De la documentación :

La solicitud ha sido aceptada para su procesamiento, pero el procesamiento no se ha completado. [...] Su propósito es permitir que un servidor acepte una solicitud para algún otro proceso (quizás un proceso orientado a lotes que solo se ejecuta una vez al día)

matsev
fuente
62
-1: Esto tendría sentido para la solicitud que inicia el proceso que eventualmente crea "cosita # 1234", pero no para la solicitud GET emitida posteriormente para la "cosita # 1234" en sí misma. En particular, un 202 sugiere que como resultado de la solicitud GET, el servicio enviará los datos de "cosita # 1234" en un momento posterior. Esto simplemente no es correcto.
Sam Harwell
77
También dice: "La entidad devuelta con esta respuesta DEBE incluir una indicación del estado actual de la solicitud y un puntero a un monitor de estado o alguna estimación de cuándo el usuario puede esperar que se complete la solicitud", por lo que esto sería un es una buena forma de informar al cliente que el blob aún no está listo y una forma de saber cuándo está listo.
Remy Lebeau
3
Yo diría que "aceptado para procesamiento" indica que está guardando la solicitud para que se actúe más tarde. Si solo se ignora, debe devolver un código 4xx o 5xx para indicar al cliente que es posible que desee volver a intentarlo.
Lucas
3
102 (procesamiento) también parece una opción razonable a veces a pesar de que está en la especificación webdav.
akostadinov
2
No puedo estar más en desacuerdo con esta respuesta. El servidor no está devolviendo nada o planea hacerlo (no está haciendo ningún procesamiento debido a esta solicitud, que de todos modos no debería para un GET). Como tal, el recurso de alguna manera no está disponible para el cliente. Esto debe tratarse como un error, por lo que no es apropiado ningún código 2XX. Algo en el espacio 4XX o 5XX. La solicitud no ha sido "aceptada para su procesamiento" , la solicitud se descarta en la práctica
Adam
52

El "problema", tal como está, está en el lado del servidor: el cliente ha hecho una solicitud bien formada, pero el servidor no puede satisfacerla. Así que estoy inclinado a un "Error de servidor", código de estado 5xx.

Quoth RFC 7231 (el estándar HTTP actual, énfasis agregado):

La clase de código de estado 5xx (Error del servidor) indica que el servidor es consciente de que ha errado o es incapaz de realizar el método solicitado . Excepto cuando se responde a una solicitud HEAD, el servidor DEBE enviar una representación que contenga una explicación de la situación de error y si es una condición temporal o permanente.

Nota

  • "erró o es incapaz de realizar la solicitud": a pesar de su título de "Error del servidor", no son solo para errores del servidor.
  • " temporal o permanente": estos códigos son adecuados para recursos temporalmente no disponibles, como el suyo.

De los códigos disponibles, yo diría que 503, "Servicio no disponible" fue la mejor opción:

El código de estado 503 (Servicio no disponible) indica que el servidor actualmente no puede manejar la solicitud debido a una sobrecarga temporal o mantenimiento programado, lo que probablemente se aliviará después de algún retraso. El servidor PUEDE enviar un campo de encabezado Retry-After ... para sugerir una cantidad de tiempo adecuada para que el cliente espere antes de volver a intentar la solicitud.

Nota:

  • "probablemente se alivie después de algún retraso": cierto para su caso.
  • "sobrecarga temporal": no es pedantemente cierto para su caso. Pero, podría argumentarse, si su servidor fuera mucho más rápido, el procesamiento por lotes ya se habría realizado cuando el cliente realizó la solicitud, por lo que es una especie de "sobrecarga": el cliente solicita recursos más rápido de lo que el servidor puede hacer ellos disponibles.
  • Reintentar es adecuado para su servicio, por lo que su respuesta debe incluir un Retry-Aftervalor. Puede proporcionar como valor el tiempo de finalización estimado de la próxima ejecución del proceso por lotes, o el intervalo de ejecución del proceso por lotes.

Definir su propio código de estado 5xx (591, por ejemplo), aunque está permitido , tendría una semántica incorrecta:

un cliente DEBE comprender la clase de cualquier código de estado, como lo indica el primer dígito, y tratar un código de estado no reconocido como equivalente al código de estado x00 de esa clase

Los clientes tratarían su propio código de estado como 500, "Error interno del servidor" , lo cual no sería correcto.

Raedwald
fuente
2
No veo cómo es mejor que 202: benramsey.com/blog/2008/04/…
JCCyC
44
@JCCyC su blog es un buen caso para devolver un 202 en respuesta a una solicitud para crear algo (POST o PUT). La pregunta parece ser preguntar qué devolver para un GET.
Raedwald
@JCCyC podría verse como un tono diferente de falta de preparación: imagine un ajax a ese recurso, ¿prefiere 202 como estado de éxito o 503 como estado de error? para que pueda ver qué significado prefiere implícitamente en el contexto de la reacción de su aplicación a la respuesta
aproximadamente el
También me gusta el aspecto práctico de "Re-Después" que va bien con algo que es "no está listo"
rloth
1
NB: "Retry-After" también puede ir bien, lo 307 - TEMPORARY REDIRECTque es bueno si desea obligar al lado del cliente a esperar en otro lugar mientras su recurso está "listo"
rloth
28

Creo que 423 - Bloqueado puede usarse para este propósito:

El código de estado 423 (Bloqueado) significa que el recurso de origen o destino de un método está bloqueado. Esta respuesta DEBE contener un código de precondición o postcondición apropiado, como 'lock-token-submit' o 'no-conflictting-lock'.

Fernando Ortega
fuente
1
Excelente respuesta! Me pregunto por qué no tiene más votos a favor.
lex82
10
¿Quizás porque es un código HTTP de WebDAV?
Stephan L
1
Desde akka-http hay StatusCode RetryWith = reg (c (449) ("Reintentar con", "La solicitud se debe volver a intentar después de realizar la acción adecuada")) donde la acción sería esperar y volver a intentar
ozma
2
En muchos sentidos estoy de acuerdo con esto. Tengo una situación similar (en mi caso, búsqueda desde un índice que aún no se puede completar). Semánticamente, creo que esto es correcto. Sin embargo, el RFC para 423 establece que "esta respuesta DEBE contener un código de precondición o poscondición apropiado, como 'lock-token-submit' o 'no-conflictting-lock'". No estoy seguro de cómo aplicar eso aquí. Y personalmente iría con 409 Conflict, pero eso fue rechazado sin comentarios, ¿no estoy seguro de por qué?
Adam
22

No quiero devolver 404; eso es para cosas que no existen.

La URL no corresponde a una solicitud de una cosita.

http://server/thingyapi/thingyblob/1234

El cliente está solicitando un thingyblob, que no existe. Si existiera, se lo darías.

404

funroll
fuente
1
¡Me alegra que alguien haya dicho esto! No puedo creer que haya tanta gente que piense que 503es una respuesta apropiada. Sin mencionar algunas de las otras sugerencias extrañas.
Jason Desrosiers
Aunque estoy de acuerdo en que un 404 es la respuesta más apropiada aquí, no responde a la pregunta del OP cómo indicar cuándo está disponible el objeto :-). Creo que el campo Reintentar después parece el mejor candidato, pero solo se puede usar oficialmente para los códigos 503 y 3xx. @ Jason: Creo que eso explica algunas de las sugerencias extrañas.
Ron Deijkers
Creo que esta es la mejor respuesta. Se le permite devolver un cuerpo en una respuesta 404. El cuerpo podría indicar que la cosita estará disponible en una fecha posterior. O utilice también el encabezado Retry-After. El estándar debe estirarse un poco aquí porque no cubre este caso muy bien.
WW.
44
Las personas se han aclimatado demasiado a la página de significado 404 que no se encuentra que no pueden disociar lógicamente eso en el contexto de una API.
The Muffin Man
1
Esto es muuuy 404. Thingyblob aún no existe, o nunca. Para http es irrelevante si alguna vez estará disponible. Por el momento no existe, y es 404. Cuando estará disponible es otro problema, que puede resolverse enviando un mensaje desde el servidor al cliente diciendo sayinblob: 1234 disponible. Realizar un encuentro de nuevo y listo ..
100r
21

Otra opción: 503 - Service Unavailable.

Brian Kelly
fuente
55
De acuerdo con W3C , no es lo que quiere decirle al cliente (aunque significa "volver de nuevo" de alguna manera): "El servidor actualmente no puede manejar la solicitud debido a una sobrecarga o mantenimiento temporal del servidor. La implicación es que esta es una condición temporal que se aliviará después de algún retraso. Si se conoce, la duración del retraso PUEDE indicarse en un encabezado Retry-After. Si no se proporciona Retry-After, el cliente DEBE manejar la respuesta como lo haría para un 500 respuesta ".
skalee
44
El servicio no está disponible, el servicio está disponible pero el procesamiento no está completo. Entonces 503 probablemente no sea una buena idea.
Ishtiaque Khan
17

Como su recurso no está listo, probablemente sepa cuándo (aproximadamente) estará disponible y cuándo el cliente puede volver a intentar su solicitud. Esto significa que es posible que desee utilizar el encabezado Retry-After . Este encabezado es válido con 503 (Servicio no disponible), lo que significa que todo el sitio está inactivo por mantenimiento y respuestas 3xx (Redirección).

En mi opinión, 302 (encontrado) con el encabezado Retry-After sería la mejor opción, pero no estoy seguro de si el campo de ubicación del encabezado de respuesta puede ser igual a la solicitud de URL. Es una redirección circular, de todos modos.

skalee
fuente
3
Incluso si está permitido, si el cliente no ha implementado el soporte para el encabezado Retry-After, una redirección 3xx a la misma página podría terminar en 503 ... (opcionalmente con un encabezado Retry-After, por supuesto)
Ron Deijkers
1
Retry-After también es válido con HTTP 429 "Demasiadas solicitudes", agregado por RFC 6585 (abril de 2012). Esto podría ser apropiado si la razón por la cual el recurso aún no está listo es que el cliente le ha dado al servidor demasiado trabajo para hacer.
Silas S. Brown el
8

409 conflicto

Indica que la solicitud no se pudo procesar debido a un conflicto en la solicitud, como un conflicto de edición en el caso de varias actualizaciones. [Fuente Wikipedia.]

Esto podría ser apropiado.

Si no puede cumplir la solicitud devolviendo los datos, entonces no es un éxito. Creo que 202 sugiere que el servidor ha puesto en cola la solicitud y la cumplirá más tarde. Pero en su caso, la solicitud es para datos ahora y ha fallado. Si vuelve a intentarlo más tarde, es una solicitud diferente.

Creo que tiene un conflicto ... desea los datos ... pero está siendo editado / actualizado. Este también sería el caso si Thingy1234 ya existiera y se hubiera descargado con éxito anteriormente, pero ahora estaba en proceso de edición, no estaba disponible mientras se realizaba la edición.

J Moore
fuente
2
No estoy seguro de por qué esto fue rechazado. Parece la respuesta correcta para mí. Del RFC: "El código de estado 409 (Conflicto) indica que la solicitud no se pudo completar debido a un conflicto con el estado actual del recurso de destino. Este código se utiliza en situaciones en las que el usuario podría resolver el conflicto y vuelva a enviar la solicitud " . Solicitó un recurso que el servidor no puede devolver porque el servidor está en proceso de actualizar ese recurso, es decir, debido al estado actual del recurso. El cliente puede resolver esto esperando y volviendo a enviar
Adam
1
@ Adam, creo que la implicación en "el usuario podría resolver el conflicto" es que algo sobre el reenvío sería diferente, además de esperar.
Desarrollador holístico
3

501 - No implementado

Exactamente como suena. Una característica que aún no está implementada, pero implica disponibilidad futura.

Aquí hay un enlace a un resumen de errores 5xx .

Dan
fuente
44
Para esta pregunta, parece que la característica en sí existe, pero el elemento que se solicita no.
Lucas
La descripción de @Luke 501 del enlace en mi respuesta, '... carece de la capacidad de cumplir con la solicitud. Por lo general, esto implica disponibilidad futura '. Esto cumple exactamente lo que pedía el OP. Independientemente de si los datos están o no en sus servidores o DB. El resultado final es que no es accesible a través de la API por el momento. Por lo tanto, la API no puede cumplir con la solicitud, pero quisiera implicar que estará disponible en el futuro a través del código http.
Dan