2008-11-20 13 views
69

Me gustaría obtener algunos consejos sobre el diseño de una API REST que permitirá a los clientes agregar/eliminar grandes cantidades de objetos a una colección de manera eficiente.Manipulación de la colección masiva a través de una API REST (RESTful)

A través de la API, los clientes necesitan poder agregar elementos a la colección y eliminar elementos de ella, así como manipular los elementos existentes. En muchos casos, el cliente querrá realizar actualizaciones masivas a la colección, p. agregando 1000 elementos y eliminando 500 artículos diferentes. Parece que el cliente debería poder hacer esto en una sola transacción con el servidor, en lugar de requerir 1000 solicitudes POST separadas y 500 DELETE.

¿Alguien tiene alguna información sobre las mejores prácticas o convenciones para lograr esto?

Mi pensamiento actual es que uno debería PONER un objeto que representa el cambio en el URI de la colección, pero esto parece estar en desacuerdo con el HTTP 1.1 RFC, lo que parece sugerir que los datos enviados en una solicitud PUT deben interpretarse de forma independiente a partir de los datos ya presentes en el URI. Esto implica que el cliente debería enviar una descripción completa del nuevo estado de la colección de una sola vez, que puede ser mucho más grande que el cambio, o incluso ser más de lo que el cliente sabría cuando realiza la solicitud.

Obviamente, me alegraría desviarme de la RFC si fuera necesario, pero preferiría hacer esto de una manera convencional si existe tal convención.

+0

¿Controla a los clientes que usan su API o necesita dar soporte a los productos de clientes existentes? En otras palabras: ¿Puede definir la semántica de las entidades de solicitud? – mkoeller

Respuesta

2

Debe usar AtomPub. Está específicamente diseñado para gestionar colecciones a través de HTTP. Incluso puede haber una implementación para su idioma de elección.

+2

En realidad, AtomPub solo define la adición de elementos individuales a una colección y su eliminación. Así que no lo llamaría "específicamente diseñado para gestionar colecciones". –

2

Para los POST, al menos, parece que debería poder enviar a una lista URL y hacer que el cuerpo de la solicitud contenga una lista de recursos nuevos en lugar de un único recurso nuevo.

1

Por lo que yo entiendo, REST significa REpresentational State Transfer, por lo que debe transferir el estado de cliente a servidor.

Si eso significa demasiados datos yendo y viniendo, quizás necesite cambiar su representación. Una estructura de cambio de colección funcionaría, con una serie de eliminaciones (por id) y adiciones (con representaciones embebidas xml completas), POSTed a una URL de interfaz de manejo. La implementación de la interfaz puede elegir su propio método para eliminaciones y adiciones en el lado del servidor.

La versión más pura probablemente sea definir los elementos por URL, y la colección contiene una serie de URL. La nueva colección puede ser PUT después de los cambios por parte del cliente, seguido de una serie de PUT de los elementos que se agregan, y tal vez una serie de eliminaciones si realmente desea eliminar los elementos del servidor en lugar de simplemente eliminarlos de esa lista.

0

Se podría introducir metarrepresentación de elementos de recogida existentes que no necesitan toda su estado transfirieron, por lo que en algún código abstracto de su actualización podría tener este aspecto:

{existing elements 1-100} 
{new element foo with values "bar", "baz"} 
{existing element 105} 
{new element foobar with values "bar", "foo"} 
{existing elements 110-200}

Adición (y modificación) elementos es hecho al definir sus valores, eliminar elementos se hace al no mencionarlo, la nueva colección y los elementos de reordenamiento se hacen especificando el nuevo orden (si el orden está almacenado).

De esta manera puede representar fácilmente toda la nueva colección sin tener que volver a transmitir todo el contenido. El uso de un encabezado If-Unmodified-Since asegura que su idea del contenido coincida con la idea de los servidores (para que no elimine accidentalmente los elementos que simplemente no sabía cuando se envió la solicitud).

+0

Si entiendo correctamente su formato de actualización propuesto, esto tiene la desventaja de no ser idempotente, ya que se refiere a los elementos de colección de una manera relativa (mediante el uso de índices) - si la actualización es 'PUT' al servidor dos veces (quizás por accidente), puede terminar con una colección corrupta; p.ej. elemento no. 105 será un elemento diferente la segunda vez que la primera vez; los diferentes elementos 101-104 serán eliminados la segunda vez. – stakx

59

Es posible que desee pensar en la tarea de cambio como un recurso en sí mismo. Entonces, realmente está PONIENDO un solo objeto, que es un objeto de Actualización masiva de datos. Tal vez tenga un nombre, propietario y gran cantidad de archivos CSV, XML, etc. que deben analizarse y ejecutarse. En el caso de CSV, es posible que también desee identificar qué tipo de objetos están representados en los datos CSV.

Enumere trabajos, agregue un trabajo, vea el estado de un trabajo, actualice un trabajo (probablemente para iniciar/detenerlo), elimine un trabajo (detenga si se está ejecutando), etc. Esas operaciones se asignan fácilmente a un Diseño de API REST.

Una vez que tenga esto en su lugar, puede agregar fácilmente diferentes tipos de datos que su actualizador de datos masivos puede manejar, tal vez incluso mezclados en la misma tarea. No es necesario tener esta misma API duplicada en toda su aplicación para cada tipo de cosa que quiera importar, en otras palabras.

Esto también se presta muy fácilmente a una implementación de tareas en segundo plano. En ese caso, probablemente desee agregar campos a los objetos de la tarea individual que permitan que el cliente de la API especifique cómo desean que se les notifique (una URL que desean que OBTENGA cuando esté terminada, o enviarles un correo electrónico, etc.) .

+2

¡Esto debe verificarse como la respuesta! – HDave

+2

Buena respuesta. Si desea aplicar una operación a un gran conjunto de recursos y los está seleccionando mediante condiciones de filtrado, puede pasar a la tarea de modificación un objeto con las condiciones del filtro. –

+2

Aunque es razonable evitar DELETE "hablador", está volviendo a la mentalidad de RPC ... Tal vez es posible OBTENER la colección, eliminar todas las cosas que desea eliminar, luego PONER la colección (usando el estado de respuesta 409 para detectar raza condiciones con modificadores concurrentes). La viabilidad de esto se reduce si el GET se busca, en cuyo caso, PATCH es probablemente la alternativa correcta. – delitescere

8

Sí, PUT crea/sobrescribe, pero no actualiza parcialmente.

Si necesita una semántica de actualización parcial, use PATCH. Ver http://greenbytes.de/tech/webdav/draft-dusseault-http-patch-14.html.

+0

Esto tiene más sentido para mí. Sin embargo, después de buscar en la web durante unas horas, este no parece ser un punto de vista común. La mayoría de los desarrolladores parecen pensar que PATCH no tiene ningún significado en una colección. –

Cuestiones relacionadas