2012-03-15 18 views
13

Diga que tiene un recurso Persona, y parte de su representación incluye un valor de Ubicación que puede tener valores como "en casa", "en la escuela" y "en el trabajo". ¿Cómo expondrías RESTfully actividades como "vete a casa", "ir a trabajar", "ir a la escuela", etc.? En aras de la discusión, estipulemos que estas actividades toman tiempo, por lo que se ejecutan de forma asincrónica, y hay varias maneras en que pueden fallar (no hay medios de transporte disponibles, interrupción del transporte durante el viaje, otro acto de Dios, etc.) . Además, el recurso Persona tiene otros atributos y operaciones asociadas que afectan esos atributos (por ejemplo, atributo = nivel de energía, operaciones = comer/dormir/ejercicio).exponiendo operaciones en recursos RESTfully: sobrecargado POST vs. PUT vs. recursos del controlador

Opción 1: sobrecarga la POST en el recurso Persona, proporcionando un parámetro de entrada que indica qué quieres que haga la persona (por ejemplo, acción = ir a la escuela). Devuelve un 202 del POST y expone los atributos de estado de actividad en progreso dentro de la representación de la persona que el cliente puede OBTENER para observar el progreso y el éxito/fracaso.

Beneficios: lo mantiene simple.

Desventajas: asciende a tunelización. La acción que tiene lugar está enterrada en la carga útil en lugar de ser visible en el URI, verbo, encabezados, etc. El verbo POST en este recurso no tiene un único significado semántico.

Opción 2: Use PUT para establecer la ubicación de la persona en el estado que desea que tengan. Devuelve un 202 del PUT y expone los atributos de actividad en progreso para el sondeo de estado a través de GET.

Beneficios: No estoy seguro de que vea alguno.

Desventajas: en realidad, esto es solo tunelización con otro verbo. Además, no funciona en algunos casos (tanto dormir como comer aumentan el nivel de energía, por lo que PONER el nivel de energía a un valor más alto es ambiguo en términos de qué acción desea que realice el recurso).

Opción 3: expone un recurso de controlador genérico que opera en objetos Person. Por ejemplo, cree un recurso PersonActivityManager que acepte solicitudes POST con argumentos que identifiquen a la Persona objetivo y la acción solicitada. El POST podría devolver un recurso de PersonActivity para representar la actividad en progreso, que el cliente podría OBTENER para monitorear el progreso y el éxito/fracaso.

Beneficios: Parece un poco más limpio al separar la actividad y su estado del recurso Person.

Desventajas: Ahora hemos movido el túnel al recurso PersonActivityManager.

Opción 4: Establezca recursos de controlador separados para cada acción admitida, p. un recurso ToWorkTransporter que acepta solicitudes POST con un argumento (o elemento URI) que identifica a la Persona, más un ToHomeTransporter, un ToSchoolTransporter, un MealServer, un Sleeper y un Exerciser. Cada uno de estos devuelve un recurso de supervisión de tareas apropiado (Commute, Meal, Slumber, Workout) de su método POST, que el cliente puede supervisar a través de GET.

Beneficios: OK, finalmente hemos eliminado el efecto túnel. Cada POST significa solo una cosa.

Desventajas: Ahora estábamos hablando de una gran cantidad de recursos (tal vez podríamos combinar los transportadores en un Transporter que acepte un argumento de destino). Y algunos de ellos son bastante semánticamente ideados (¿un Durmiente?). Puede ser más RESTful, pero ¿es práctico?

+1

¿Por qué piensa que una acción que poner en un nombre de recurso es una buena idea? POST significa "hacer algo basado en este documento", pero si los documentos son diferentes, la acción desencadenada también puede ser –

+4

Exponer procesos como recursos es una recomendación común en conversaciones de diseño RESTful. En RESTful Web Services (O'Reilly), los autores sugieren que "si tiene la tentación de exponer objetos o procesos complejos a través de una POST sobrecargada, intente dar a los objetos o procesos sus propios URI y exponerlos". ellos como recursos ". En RESTful Web Services Cookbook (O'Reilly), en la receta 2.6, el autor dice "Designe un recurso de controlador para cada operación distinta". En REST In Practice (también O'Reilly) el autor describe un sistema de cafetería con un recurso de pedido que acepta POST. –

Respuesta

16

OK, he estado investigando y reflexionando sobre esto durante aproximadamente una semana. Como nadie más ha respondido, publicaré los resultados de lo que he aprendido.

Tim Bray, en RESTful Casuistry, se refiere a PONER un campo de estado vs POST-ing a un controlador que realizará una operación que afecte ese estado. Utiliza el ejemplo de una máquina virtual y cómo exponer de forma RESTANTE la función de un "botón de reinicio". Dice

"Si quiero actualizar algunos campos en un recurso existente, me siento inclinado a pensar PUT. Pero eso no funciona, ya que se supone que es idempotente, y reiniciar un servidor seguro . no está bien, está bien, hacerlo con POSTAL supongo;. no hay problema

Pero usted no está realmente cambiando un estado, que está solicitando un conjunto específico de acciones a ocurrir, como resultado de que el estado puede o puede no alcanzar el valor deseado. De hecho, cuando presionas el interruptor de implementación, el estado cambia a implementación y luego a algún imprevisible cantidad de tiempo para desplegar. Y la operación de reinicio es la clásica caja de con un gran interruptor rojo en el lateral; el problema es cómo presionar el interruptor.

Por lo tanto, cuanto más lo pienso, más pienso que estos recursos son como botones, con solo una operación definida: pulsar. La gente ha estado quejándose de "recursos de solo escritura", pero no tengo un problema con porque parece exacto. Los botones de reiniciar y detener no tienen realmente ningún estado, por lo que no debe esperar nada útil a partir de un GET ."

Tim parece asentarse en algún lugar entre mi opción # 3 y # 4, la exposición múltiple recursos del controlador, pero alejándose de "ir por la borda" y tener recursos de controlador separados para todo.

La publicación de Tim llevó a otra por Roy Fielding (It is OK to use POST) en la que dice que para situaciones donde hay un estado de entidad supervisable, una acción para potencialmente cambiar ese estado, se inclina a usar POST en lugar de PUT. En respuesta a la sugerencia de un comentarista de exponer el estado supervisado como un PUT-recursos capaces separada, dice

"Sólo utilizamos PUT cuando la acción de actualización es idempotente y la representación es completa. Creo que deberíamos definir un recurso adicional cuando creamos que ese recurso podría ser útil para otros en el aislamiento , y hacer uso de los métodos GET/PUT para ese recurso, pero No creo que debamos definir nuevos recursos solo para por el bien de evitando POST."

Finalmente, Bill de Hora, en Just use POST analiza el caso concreto de la utilización de PUT vs. POST para actualizar el estado de un recurso colección, y las ventajas y desventajas en el mismo.

+0

Dado que ha pasado un tiempo y no hay otras respuestas, acepto esta. –