RESTful дизайн ресурса с бинарными состояниями

У меня есть ресурс, который по существу является простым CRUD-документом, который имеет небольшой поворот в том, что его можно "переключить" в "синхронизированное" состояние "туда-сюда" вместо использования его собственных текущих значений, теперь оно возвращает значения "родительский" документ, с которым он теперь синхронизирован.

Я пытаюсь найти RESTful способ моделирования этого. Ресурс имеет свойство, которое указывает это состояние Synchronzied = true/false и ParentId, чтобы указать, с каким ресурсом он синхронизируется.

Один из вариантов заключается в том, чтобы просто изменить это во время обновлений PUT, но это кажется некорректным, поскольку это не является частью документа, но в некоторых отношениях это метаданные о документе. Я также рассмотрел запрос POST /document/{id}/synchronized, в котором запрашиваемое состояние передается в качестве аргумента.

Ничего не получается. Первое ощущение немного неудобно, потому что кажется, что я разбираю представленные данные только для одного значения, остальные существенно отбрасываются, если мы синхронизируем. Во втором случае неправильно создавать вложенный ресурс только для одного свойства.

Ответ 1

Одно из решений состоит в том, чтобы иметь два разных типа ресурсов - полные документы и подчиненные документы - отличающиеся по типу MIME. Например, вы можете иметь application/vnd.mysite.document для полного документа и application/vnd.mysite.documentlink+json, когда вы просто связываетесь с другим документом.

Чтобы создать подчиненный документ:

PUT /document/1234
Content-Type: application/vnd.mysite.documentlink+json

{"parent": "/document/1"}

Чтобы сделать полный документ:

PUT /document/1234
Content-Type: application/vnd.mysite.document

Hello, I am a document full of stuff.

Затем вы можете отвечать на запросы GET, возвращая документ или ссылку 303 (см. раздел "Прочее" ) на родителя.

Ответ 2

В ответ на GET на синхронизированный ресурс вы можете подумать о возврате 302/303 с заголовком Location, установленным для родительского ресурса. Но затем разрешите PUT на том же синхронизированном URI, чтобы заменить перенаправление переданным объектом, который затем будет возвращен в последующих ответах GET. Если вы хотите разрешить клиентам переключать объект обратно в синхронизированное состояние, вы можете сделать это, выполнив POST для дочернего URI тела запроса, содержащего URI желаемого родителя. Вы даже можете найти случайные варианты использования, разрешив клиенту POST любой URI, а не только идентификатор небольшого набора известных родителей.

GET /child
    200 OK
    {foo: bar}

POST /child
{parent: /some/other}
    200 OK

GET /child
    302/303
    Location: /some/other

PUT /child
{foo: baz}
    201 Created

GET /child
    200 OK
    {foo: baz}

Ответ 3

Вы просмотрели большинство общих опций, однако подумайте об использовании метода HTTP PATCH. Я успешно использовал его через AJAX как в Firefox, так и в Chrome. Метод PATCH указывает набор изменений, которые должны применяться к документу, а не замена всего документа (через PUT).

(Если вы хотите получить только часть документа, подумайте о том, чтобы указать Range header с GET. Вам нужно будет определите что-то другое, кроме байтового диапазона, для работы с документами XML или JSON - подробнее см. единицы измерения диапазона.)

Очевидно, что оба этих решения предполагают, что клиент и сервер готовы - если вы не можете поддерживать API на обоих концах запроса, у вас тоже не будет большого успеха.