2011-02-22 22 views
45

Estoy escribiendo una API REST para un servicio que aceptará datos aportados por el usuario. Me gustaría mantener todas las operaciones completamente asincrónicas, esto incluye las solicitudes PUT, POST, DELETE e incluso GET. Mi idea es recibir la solicitud, procesarla lo suficiente como para garantizar que sea una solicitud válida y luego aprobar una respuesta aceptada HTTP 202 junto con una url donde los datos estarán disponibles y un token para que las solicitudes subsiguientes puedan coincidir con los datos procesados . Si la solicitud no es válida, entonces enviaré un HTTP 400.Usar el estado HTTP 202 para operaciones asincrónicas

El cliente será responsable de verificar la url que les proporcioné en algún momento en el futuro y pasar el token. Si los datos están disponibles, devuelvo un 200 o 201 normal, pero si aún estoy procesando la solicitud, enviaré otro 202 indicando que el procesamiento no se ha completado. En caso de errores al procesar los datos, enviaré el estado 4xx o 5xx según sea necesario.

La razón por la que quiero hacer esto es para poder volcar todas las solicitudes válidas en un grupo de solicitudes y hacer que los trabajadores extraigan de la cola y procesar las solicitudes, ya que están disponibles. Como no conozco el tamaño del grupo o la cantidad de trabajadores disponibles, no puedo estar seguro de poder atender las solicitudes lo suficientemente rápido como para cumplir el límite de 30 segundos de Google App Engine.

Mi pregunta es: ¿estoy pervirtiendo REST procesando solicitudes de esta manera? Los navegadores, por ejemplo, parecen requerir respuestas inmediatas a las solicitudes. Para mis páginas HTML, planeo responder con la página estructurada y luego usar AJAX para procesar las solicitudes de datos.

Principalmente estoy interesado en cualquier opinión o experiencia en el procesamiento de datos usando REST de esta manera.

+0

¿Espera navegadores que utilizan esta directamente? Debido a que esta solución parece adecuada para una API (consulte la respuesta de @systempuntoout), obviamente no funcionará para un navegador web. –

+0

Voy a intentar limitar los navegadores a las operaciones GET con las consultas más probables retenidas en la memoria (por ejemplo, memcached). Es probable que las consultas a más largo plazo se realicen a través de AJAX utilizando sondeos con un indicador de progreso mostrado (por ejemplo, filtrado de grandes conjuntos de resultados). PUT y POST probablemente serán similares a subir videos de youtube donde le doy al usuario un mensaje estándar "su medio está siendo procesado" hasta que el servidor haya completado la tarea. –

+0

Algunos recursos para restapi http://stackoverflow.com/questions/14124056/rest-api-202-versus-204/27766943#27766943 –

Respuesta

29

creo que la solución está muy bien, la Http status 202 es el proper response a usar en este caso específico que indica que la solicitud ha sido admitida a trámite, pero el tratamiento no se ha completado.

Lo que cambiaría ligeramente en su flujo de trabajo es el Http status de las solicitudes posteriores.

Como dijo, el 202 response debe devolver un Location header especificando la URL que el cliente debe usar para supervisar el estado de su solicitud anterior.
Al llamar a este Registro de la estatuto de las mi- proceso de URL, en lugar de devolver un 202 en caso de proceso pendiente, volvería:

  1. 200 OK cuando el proceso solicitado aún está pendiente. La respuesta debe describir el estado pendiente del proceso.
  2. 201 Created cuando se ha completado el procesamiento. La respuesta en caso de GET/PUT/POST debe contener la ubicación del recurso solicitado/creado/actualizado.
+1

Acepto sus respuestas de estado. Se siente un poco incómodo enviar el mensaje 200 OK mientras estoy procesando, ya que sugiere que "La solicitud ha tenido éxito". Sin embargo, 202 también sugiere que la solicitud ha sido aceptada, que no es el caso cuando solo estoy verificando el progreso. No hay exactamente un estado para describir lo que quiero, así que 200 podría significar "tan bien". –

+12

Estoy de acuerdo con esto, pero no creo que ni '201' ni' 202' tengan sentido para las solicitudes de seguimiento. Los códigos de estado están destinados a indicar el estado de la solicitud/respuesta - _no_ el recurso. Quédese con '200' en las solicitudes de seguimiento y use la representación para representar el estado del recurso. –

+0

¿hay algún código de muestra? – plzdontkillme

21

Agregando mis dos centavos a una pregunta anterior. Mi idea es similar a systempuntoout y las sugerencias de Avi Flax.

Acepto que una respuesta HTTP 202 es apropiada para la solicitud inicial con un redireccionamiento a otro recurso a través de un encabezado Location.

Creo que la URL Location probablemente debería incluir el token que usted hace referencia para cumplir con las expectativas comunes de un Location redirigir. Por ejemplo, Location: /queue?token={unique_token} o Location: /task/{unique_token}.

También creo que el recurso utilizado para verificar el estado del proceso debe devolver una respuesta HTTP 200 cuando la acción de "verificar el estado" es exitosa (no es HTTP 202 porque eso implica que la solicitud actual fue "aceptada").

Sin embargo, creo que cuando se crea la nueva entidad "Comprobación del estado" debe devolver una respuesta HTTP 303 (See Other) con una cabecera Location para la nueva entidad una vez que ha sido creado. Esto es más apropiado que enviar un HTTP 201 porque no se creó nada debido a la solicitud GET que se acaba de realizar para verificar el estado.

También creo que el recurso utilizado para verificar el estado debe devolver los códigos de error de forma adecuada. Siempre que "verificar el estado" se realice con éxito, se debe devolver un código de éxito apropiado. Los errores se pueden manejar en el nivel de la aplicación (verificando el cuerpo de la respuesta).

+0

Me gusta la idea de usar un redireccionamiento 303 para que el cliente complete la solicitud en una URL diferente. Al mirar la página de wikipedia que vinculó también se describe su uso para exactamente mi propósito original. Gracias por la respuesta. –

6

Esta es una pregunta muy antigua, pero me gustaría ofrecer una vista ligeramente diferente de esto, que no pretendo ser correcta, solo mi opinión.

Desde la perspectiva del cliente

Vamos a empezar con la solicitud HTTP inicial. En primer lugar, la solicitud debe ser POST. Está enviando un mensaje al servidor para crear un recurso. GET y PUT no son válidos en este caso porque:

  • un GET no es válida en este contexto porque un GET está destinado a obtener el recurso en un lugar específico
  • una opción de venta no es válida porque no está al crear la solicitud, le está pidiendo al servidor que cree la solicitud.

Desde la perspectiva de servicio

Así que ya lo están enviando una solicitud POST al servidor para procesar una solicitud. El servidor tiene en realidad 3 valores de retorno posibles (sin incluir los 4xx y 5xx errores):

  • "201 Created" indica que el servicio tiene la petición y fue capaz de procesar inmediatamente o dentro de un periodo de tiempo aceptable. Este período de tiempo depende completamente del diseño del servicio. Depende del desarrollador del servicio definir esto.
  • "202 aceptada" indica que el servicio recibió la solicitud y la está procesando. Esto se usa cuando el servicio sabe que algo tardará un tiempo. La otra perspectiva es que si el servicio depende de cualquier otra operación asincrónica que no tiene manera de determinar el resultado, entonces debe devolver la respuesta "202 aceptada". Finalmente, algunos diseñadores de servicios simplemente siempre pueden devolver "202 aceptados", independientemente de qué tan rápido se pueda hacer.
  • En algunos casos, obtendría un "302 Encontrado". Esto es generalmente cuando el servicio puede identificar una solicitud como la generación de un recurso que ya existe (y aún es válido y no está en un estado de error) y que la reutilización de un recurso existente es aceptable. No todos los servicios funcionan de la siguiente manera: publicar un comentario en un hilo siempre debe crear nuevos recursos. Otros servicios sí: publican un conjunto de criterios para obtener una lista de médicos que produce la misma lista de médicos. Si esta información se puede reutilizar, reutilícela.
  • Con todas estas respuestas, el encabezado HTTP "Ubicación" se devuelve al cliente que contiene donde se puede encontrar el recurso.Esto es importante y algunas personas tienden a divergir en su enfoque, como verá más adelante. Si el recurso se puede reutilizar con otras solicitudes, la "Ubicación" realmente se debe generar de manera que las mismas solicitudes siempre generen las mismas URL. Esto proporciona una gran cantidad de almacenamiento en caché y reutilización.

Cuando el servicio ha completado la solicitud con éxito, creará el recurso en la ubicación que se devolvió al cliente.

Ahora aquí es donde comienzo a ver cosas un poco diferentes de la respuesta anterior.

Si el servicio no puede completar la solicitud, aún debe crear un recurso en la ubicación que se devolvió al cliente. Este recurso debe indicar el motivo de la falla. Es mucho más flexible tener un recurso que brinde información de falla que tratar de conectarlo al protocolo HTTP.

Si el servicio obtiene la solicitud de este recurso antes de que se complete, debe devolver un "404 No encontrado". La razón por la que creo que debería ser un "404 no encontrado" es porque realmente no existe. Las especificaciones HTTP no dicen que "404 no encontrado" solo se puede usar cuando un recurso nunca va a existir, solo que no existe ahora. Este tipo de respuesta a un flujo de sondeo asíncrono es completamente correcto en mi opinión.

También existe la situación de cuando se supone que un recurso solo debe estar allí durante un tiempo fijo. Por ejemplo, pueden ser datos basados ​​en una fuente que se actualiza todas las noches. Lo que debería suceder en estos casos es que el recurso debe eliminarse, pero se debe proporcionar un indicador al servicio que pueda saber para devolver un código de estado "410 Gone". Esto básicamente le dice al cliente que el recurso estaba aquí, pero ya no está disponible (es decir, puede haber expirado). La acción típica del cliente sería volver a enviar la solicitud.

Desde la perspectiva del cliente nuevo

Cuando el cliente recibe la respuesta por su mensaje inicial, se obtiene el "Lugar" y hace la solicitud al servicio a través de la URL utilizando un GET (de nuevo, no la POST) El servicio generalmente responderá con estos valores:

  • "200 OK" indica que la solicitud se completó. El resultado de la solicitud se devuelve en el cuerpo del contenido, proporcionando el contenido en el formato definido por el encabezado Aceptar de HTTP.
  • "404 Not Found" le indica al cliente que la solicitud no se completó aún, el recurso aún no está allí y, en este caso, básicamente debería intentarlo más tarde.
  • "410 Gone" se devolverá en casos donde el cliente puede intentar obtener el recurso después de un largo período de tiempo y ya no está allí. En este caso, simplemente debe volver a enviar la consulta original

Lo único que debe señalarse es que el recurso que se devuelve generalmente está en un formato que puede definir respuestas exitosas y fallidas. El cliente debería poder determinar a partir de este recurso si hubo un error, cuál fue y poder responder en consecuencia.

Además, el desarrollador del servicio puede hacerlo para que el servicio caduque y elimine el recurso de error después de un corto período de tiempo.

Así que esa es mi opinión sobre esta cuestión. Es muy tarde para la fiesta, pero es de esperar que los futuros lectores puedan ver una opinión ligeramente diferente a una pregunta frecuente.

+3

El problema con 404 es que es almacenable en caché. (Ver http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-25#section-6.1). Reintentar un 404 hasta que tenga éxito probablemente no sea un buen patrón para usar y parece muy no estándar. Los errores 4xx son específicamente errores del cliente. Los errores 4xx implican que el cliente cometió un error o no pasó la información necesaria para acceder a un recurso. En el uso normal, obtener un encabezado de ubicación que se resuelve en 404 es un error. (Por ejemplo, una condición de carrera o un problema de coherencia de la base de datos). – ngreen

+2

Buenos puntos. El problema de caché se puede resolver mediante los encabezados HTTP de control de caché. Con respecto al segundo punto, ese es un buen punto. Técnicamente, no es un uso incorrecto de 404, pero aparece una preocupación válida. –

+1

Podría considerar utilizar el encabezado Content-Location para recuperar un estado de la operación. De lo contrario, estoy de acuerdo con Dino. La inspiración para Content-Location se puede encontrar aquí en Microsoft Azure: https://docs.microsoft.com/en-us/rest/api/hdinsight/asynchronous-operations--202-accepted-and-location-header- –

1

FWIW, Microsoft Flow utiliza un patrón como este.
La primera llamada devuelve 202 con cabecera de ubicación. Las llamadas de seguimiento vuelven: 1. Si todavía está procesando -> 202 con un encabezado de ubicación. El encabezado de loc puede ser diferente, lo que proporciona una forma de pasar el estado entre llamadas (¡y potencialmente hacer que el servidor sea sin estado!). 2. Si se hace -> 200.

detalles en: https://github.com/jeffhollan/LogicAppsAsyncResponseSample

Cuestiones relacionadas