Как вы RESTful создавать и удалять одновременно? - PullRequest
2 голосов
/ 30 июня 2011

Допустим, у меня есть приложение для планирования поездки, и каждая поездка состоит из ресурсов «пути» (например, представляющих маршрут, который нужно проехать), состоящих из последовательности точек. Я могу CRUD эти ресурсы, используя такие запросы (просто пример):

POST /trips/1234/paths

<Path>
  <Point>32,32</Point>
  <Point>32,34</Point>
  <Point>34,34</Point>
</Path>

DELETE /trips/1234/paths/3

Теперь учтите, что я хочу иметь возможность разделить Путь на два пути. В примере aobve я мог бы выбрать точку (32,34) для разделения, что приведет к двум путям - один заканчивается в этой точке, другой начинается в этой точке. Это означает, что одно действие создает два новых ресурса и одновременно удаляет другое (путь, который был разделен).

Таким образом, если путь в приведенном выше примере был единственным путем в системе, и я разделил его одним вызовом, система теперь будет содержать два новых пути, а исходный будет удален. Пример:

<Path>
  <Point>32,32</Point>
  <Point>32,34</Point>
</Path>

<Path>
  <Point>32,34</Point>
  <Point>34,34</Point>
</Path>

Я борюсь с тем, как это будет обрабатываться RESTful. Как обрабатывать вызовы, которые приводят к созданию / изменению / удалению нескольких ресурсов, и сообщать об этом вызывающей стороне?

Я могу определенно разобраться с несколькими вызовами (два POST для создания новых путей и DELETE для удаления оригинала), но я хочу, чтобы это был один вызов.

Ответы [ 4 ]

2 голосов
/ 30 июня 2011

Это не совсем красиво, но это можно решить с помощью "ресурса обработки"

POST /PathSplitter?SplitAt=(32,34)
Content-Type: application/vnd.acme.path+xml
<Path>
  <Point>32,32</Point>
  <Point>32,34</Point>
  <Point>34,34</Point>
</Path>

=>
200 OK
Content-Type: application/vnd.acme.pathlist+xml
<Paths> 
   <Path href="/trips/1234/paths/4"/>
   <Path href="/trips/1234/paths/5"/>
</Path>
1 голос
/ 01 июля 2011

Я бы попробовал реализовать это как @ Даррел Миллер ответ, но сделать его чуть менее RPCish. Идея состоит в том, чтобы создать ресурс PathSplit, который будет направлять клиента на каждом этапе выполнения транзакции. Таким образом, клиент знает результат каждого шага и знает, как отступить, если в процессе возникнет ошибка.

Нечто подобное должно сработать.

POST /pathsplit HTTP/1.1
Content-Type: application/vnd.acme.pathsplit+xml
<pathsplit xmlns="http://schema.acme.com">
  <path>
    <id>123</id>
  </path>
  <splitpoint>
      <point>32,34</point>
  </splitpoint>
</pathsplit>

=>
HTTP/1.1 201 Created
Content-Type: application/vnd.acme.pathsplit+xml
Location:
  http://acme.com/pathsplit/11

<pathsplit xmlns="http://schema.acme.com">
  <path>
    <id>123</id>
  </path>
  <splitpoint>
      <point>32,34</point>
  </splitpoint>
  <newpaths>
    <Path>
      <Point>32,32</Point>
      <Point>32,34</Point>
    </Path>
    <Path>
      <Point>32,34</Point>
      <Point>34,34</Point>
    </Path>
    <createuri>http://acme.org/trips/paths</createuri>
  </newpaths>
  <oldpath>
    <uri>http://acme.org/trips/paths/123</uri>
  </oldpath>
    <status>in-progress</status>
    <pathscreated>0</pathscreated>
</pathsplit>

С чем-то вроде этого клиент всегда может GET ресурс pathsplit, чтобы увидеть, какие действия предпринять. В этом примере он будет создавать как новый paths по ссылке createuri, так и отправлять запрос POST для каждого нового path в newpaths. Сервер обновляет статус при создании каждого нового ресурса.

Когда статус имеет pathscreated из 2, клиент может удалить старый path, следуя uri и отправив глагол DELETE. Наконец, он удалит ресурс pathsplit, что означает, что все прошло успешно.

На каждом этапе пути, в случае ошибки или в слишком частом случае сбоя в сети, клиент всегда знает, в каком состоянии находится сервер и в каком состоянии находится транзакция.

Ресурс Pathsplit остается доступным, пока транзакция не завершена. У клиента также есть возможность отменить транзакцию, которая еще не завершена. Опять же, поскольку он знает, какие операции успешно завершены, а какие нет, он всегда может отменить транзакцию.

1 голос
/ 30 июня 2011

Короткий ответ: сделать один вызов просто не очень приятно;если вы не переделываете свои представления, я понимаю, что REST и HATEOAS таковы, что процесс такого рода пытается ввести глагол в представление на стороне сервера, что является большим нет-нет.Это не значит, что то, что вы хотите сделать, не может быть выполнено RESTful, но я думаю, что это требует некоторого рефакторинга вашего дерева представления.быть одним звонком;Я понимаю, почему это имеет смысл с точки зрения транзакций.Казалось бы, это подразумевает предоставление клиенту представления REST транзакции, чтобы клиент мог правильно управлять транзакциями.Я не говорю, что это просто, хотя ...

0 голосов
/ 30 июня 2011

Решение со строгими операциями CRUD здесь не кажется мне полезным.Однако операции над ресурсами не обязательно должны быть операциями CRUD.Многие даже думают об этом как о плохом способе разработки интерфейса REST (просто google для отдыха + crud).

Итак, я думаю, что все нормально, когда вы определяете операцию split как один вызов REST.Поскольку вы применяете эту операцию только к одному ресурсу (исходному пути), вы можете определить эту операцию непосредственно для него.Нет необходимости определять его для нескольких ресурсов.

...