Вы можете обрабатывать обновления другим способом. Первый вопрос: как вы, клиенты, знаете, как обновить ресурс? Если они получают информацию внеполосно, то вы не делаете REST. Включая информацию об обновлении в полосе, он делает явное обновление и тем самым дает вам гораздо большую свободу и гибкость. Например, ресурс product
может быть представлен следующим образом
<product href="/products/123"
name="iPad 64GB + 4G"
price="829.00">
<description>It's cool, ya</description>
<update href="/products/123" method="PUT">
<name type="xs:string" cardinality="optional"/>
<price type="xs:decimal" cardinality="optional"/>
<description type="xs:string" cardinality="optional"/>
</update>
... you could have a delete form here as well ...
</person>
Между тем, коллекция products
может быть представлена как
<people href="/products">
... the first set of items in the collection and pagination links could go here ...
<create href="/product" method="POST">
<name type="xs:string" cardinality="required"/>
<price type="xs:decimal" cardinality="required"/>
<description type="xs:string" cardinality="required"/>
</create>
</people>
Обратите внимание, как кардинальность аргументов различается между update и create.
С точки зрения замены PUT всего состояния ресурса, подумайте об этом следующим образом: Когда я обновляю product
и указываю только price
, name
и description
по умолчанию сохраняют свои существующие значения, а затем Весь ресурс обновляется. Единственное, что нам нужно сделать, это четко определить эту логику в нашем медиа-типе.
Из того, что вы описали, в настоящее время у вас есть нечто, что можно представить в виде
<product href="/products/123"
name="iPad 64GB + 4G"
price="829.00">
<description>It's cool, ya</description>
<update href="/products/123" method="PUT">
<product type="my:product" cardinality="required"/>
</update>
... you could have a delete form here as well ...
</person>
<people href="/products">
... the first set of items in the collection and pagination links could go here ...
<create href="/product" method="POST">
<product type="my:product" cardinality="required"/>
</create>
</people>
Это неплохо, просто обновления вроде отстой, потому что вы должны включить все поля. Вы правы, когда чувствуете, что это неправильно, и подвергаете сомнению это.
Кроме того, я настоятельно рекомендую вам не использовать XSD для проверки запросов. Если XSD не разработан очень тщательно, он создаст тесную связь между вашими клиентами и вашим API, что заставит вас обновлять оба одновременно или в определенном порядке (например, сервер, затем клиент). Взгляните на Schematron вместо.
Теперь, с точки зрения order
, который будет иметь детали status
или dispatch
, представьте ресурс order
как маленький конечный автомат. Это может выглядеть так:
Start ----> Received ----> Processed -------> Dispatched ------> End
| | ^
| V |
----------> Cancelled ------------------------------
Таким образом, когда заказ создается, он автоматически получает статус, установленный для получения. Оттуда он может либо быть обработан, либо отменен, а из обработанного он может либо отправляться, либо отменяться. Идея состоит в том, чтобы представить переходы через формы и ссылки, представленные в ресурсе. Основываясь на этом, вот как мы можем представить order
для различных состояний
Получено (с точки зрения клиента):
<order href="/orders/123" status="received">
... order details go here ...
<cancel href="/orders/123" method="delete"/>
</order>
Получено (с точки зрения работника):
<order href="/orders/123" status="received">
... order details go here ...
<process href="/orders/123" method="put">
... whatever details need to be submitted at the same time ...
</process>
</order>
Обработано (с точки зрения клиента)
<order href="/orders/123" status="processed">
... order details go here ...
<cancel href="/orders/123" method="delete"/>
</order>
Обработано (с точки зрения сотрудника):
<order href="/orders/123" status="processed">
... order details go here ...
<dispatch href="/orders/123" method="POST">
<company type="xs:string" cardinality="required"/>
<con-note type="xs:string" cardinality="required"/>
<tracking type="xs:anyURI" cardinality="optional"/>
... whatever details need to be submitted at the same time ...
</dispatch>
</order>
Отправлено (с точки зрения клиента и сотрудников)
<order href="/orders/123" status="dispatched">
... order details go here ...
<shipping-details href="/order/123/shipping">
</order>
Отменено (с точки зрения клиента и сотрудников)
<order href="/orders/123" status="cancelled">
... order details go here ...
</order>
Различные переходы состояний представляются разным пользователям на основании их разрешений. Сотрудник не может отменить заказ и аналогичным образом клиент не может обработать или отправить заказ. Также в зависимости от текущего состояния заказа представлены только разрешенные переходы между состояниями.