построение RESTful API - обработка запросов POST и проверка - PullRequest
2 голосов
/ 07 марта 2012

Я создаю API и пытаюсь найти лучший способ справиться с публикацией и обновлением ресурсов. На данный момент пользователь будет публиковать данные на ресурс продуктов с использованием XML. Я проверяю этот XML по файлу xsd. Это прекрасно работает, но означает, что пользователи, желающие обновить одно поле, должны опубликовать все поля, относящиеся к продукту. Ожидается ли это или я должен делать это как-то иначе?

У меня есть другой ресурс, который будет нуждаться в обновлении "status" или "dispatched", но будет обновлять только одно или другое, но не одновременно. Поэтому я бы построил это таким же образом, как у меня есть ресурс продукта и потребовал бы, чтобы они всегда ЗАПИСЫВАЛИ оба поля, даже если будет обновлено только одно, или имеют два отдельных ресурса?

Ответы [ 2 ]

2 голосов
/ 08 марта 2012

Вы можете обрабатывать обновления другим способом. Первый вопрос: как вы, клиенты, знаете, как обновить ресурс? Если они получают информацию внеполосно, то вы не делаете 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>

Различные переходы состояний представляются разным пользователям на основании их разрешений. Сотрудник не может отменить заказ и аналогичным образом клиент не может обработать или отправить заказ. Также в зависимости от текущего состояния заказа представлены только разрешенные переходы между состояниями.

1 голос
/ 07 марта 2012

С POST вы можете гибко определять, какое состояние вы определяете для данного ресурса. POST может быть своего рода универсальным методом. Если бы вы использовали метод PUT, вам нужно было бы заменить все состояние ресурса, поскольку спецификация HTTP определяет это как правильное поведение. На самом деле может иметь смысл создавать отдельные ресурсы для статуса и отправлять их с собственным поведением GET / POST / PUT / DELETE для представления описанного вами варианта использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...