Как смоделировать редактирование утвержденных ресурсов для создания черновиков ресурсов в REST API - PullRequest
1 голос
/ 28 мая 2020

Сценарий использования - это обработка Конфигурации, которая должна быть рассмотрена и утверждена пользователями, прежде чем ее можно будет использовать. Проблема заключается в моделировании случая редактирования для уже утвержденной Конфигурации.

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

Это немного отличается от этого вопроса ( Architectural REST: Как мне спроектировать REST API для запроса + утверждения, 2 ресурса или 1? ), поскольку он не охватывает обновление уже утвержденного ресурса.

Один из подходов - иметь ресурс конфигурации с ожидающими и утвержденными подресурсами, например

/configurations/A/pending
/configurations/A/approved

(Первый / configurations / A / pending может быть создан, / configurations / A / pending может быть исправлен таким образом, что / configurations / A / authorized существует и / configurations / A / pending удален. Похоже допустимо, чтобы операция исправления имела побочные эффекты для других ресурсов (https://tools.ietf.org/html/rfc5789#section -2 ))

Тогда возникает вопрос: как обрабатывать случай редактирования для утвержденного Конфигурация, которая должна создать ожидающую конфигурацию.

Если бы мы отредактировали A, операция PUT могла бы быть применена к / configurations / A / authorized, но это кажется странным, так как результатом будет создание / configurations / A / pending. Но операция PUT должна быть идемпотентной и не иметь побочных эффектов.

Мы могли бы иметь операцию PUT для / configurations / A / pending, но это также кажется странным, поскольку логически мы хотим выполнить операцию на утвержденном ресурсе.

Вместо того, чтобы иметь отдельную конфигурацию с подресурсами, мы могли бы смоделировать отдельные ожидающие и одобренные ресурсы следующим образом:

/configurations/pending/A
/configurations/approved/A

or we could go a step further and decouple the two and have different ids
/configurations/pending/123
/configurations/approved/A

Но та же проблема, что и перечисленная выше, все еще остается.

Хотел бы услышать другие мысли о том, как моделировать редактирование утвержденного ресурса.

1 Ответ

0 голосов
/ 29 мая 2020

Но операция PUT должна быть идемпотентной и не иметь побочных эффектов.

Согласно RF C 7231 PUT также может иметь побочные эффекты, т.е. если вы разрабатываете систему, подобную фиксации, подобную Git, где фиксация создает новую запись фиксации в дереве ветвей, одновременно перемещая HEAD в самую последнюю версию.

В качестве дальнейшего фона, управление версиями и отслеживание истории черновиков выходит за рамки, пользователи будут коллективно одобрять один незавершенный черновик. Одобренная конфигурация может быть обновлена ​​снова с помощью другого незавершенного черновика, поэтому утвержденные и ожидающие рассмотрения конфигурации могут быть доступны бок о бок. все конфигурации и черновики, а также ссылки на каждую запись для редактирования и удаления такой конфигурации / черновика. Поскольку только черновики могут быть приняты / отклонены, в зависимости от того, является ли данный ресурс черновиком или нет, может содержаться возможность принять / отклонить его.

Как уже упоминалось, принятие черновика должно привести к удалению черновика и создание / замена актуальной конфигурации. На самом деле есть несколько способов добиться этого, в зависимости от того, как вы проектируете вещи. В общем, URI в целом, как следует из названия, представляет собой уникальный идентификатор ресурса. Сегменты в этом URI не обязательно автоматически определяют родительско-дочерние отношения. Можно создать набор URI, которые отображают такое дерево предков на ресурсы, которые сервер рассматривает как родительские и дочерние.

PATCH - это, по сути, операция, при которой клиент должен вычислить набор инструкций, которые сервер должен применить для атомарного преобразования целевого ресурса из его текущей формы в желаемую. Таким образом, либо все инструкции выполнены успешно, либо не выполняются вовсе. В зависимости от выбранного типа представления (подсказка: согласованный тип мультимедиа) такая операция может быть выполнима.

С JSON Patch (application/json-patch+json) вам необходимо настроить таргетинг на ресурс-предок, который вы обращаетесь к перемещаете этот ресурс в другое место. Такая полезная нагрузка может выглядеть следующим образом:

PATCH /configurations HTTP/1.1
Host: www.acme.com
Content-Type: application/json-patch+json; charset="utf-8"
ETag: 33a64df551425fcc55e4d42a148795d9f25f89d4
...

[
  { 
    "op": "move", 
    "from": "/drafts/eaff31bd-5291-4287-a7dd-fbe5b1e47b67", 
    "path": "/approved/eaff31bd-5291-4287-a7dd-fbe5b1e47b67" 
  }
]

Это в основном ставит перед сервером задачу переместить указанный ресурс черновика и переместить его в утвержденные ресурсы конфигурации. Я только что взял здесь предложенные вами имена. В архитектуре REST они не имеют особого значения. Поскольку этот запрос должен быть создан клиентом, в идеале сервер уже предоставляет клиенту все данные, необходимые для создания такого запроса. В Интернете HTML поддерживает такую ​​функцию с помощью веб-форм , которые определяют допустимый синтаксис и семантику каждого из элементов и атрибутов. Для JSON HAL-FORMS и Ion могут быть использованы для поддержки вас в этой задаче.

В отличие от JSON Patch, JSON Merge-Patch , который определяет набор правил по умолчанию, применяемых к документу, однако не позволит вам перемещать документ, если вы не примените на сервере пользовательский logi c.

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

Хотя PUT может иметь побочные эффекты, они более или менее ограничиваются созданием новых ресурсов в результате замены документа. Вы можете «изменить свой дизайн» таким образом, чтобы отправить пустой запрос PUT в текущий черновик, что приведет к тому, что сервер скопирует текущий контент в принятые конфигурации. Поскольку PUT является небезопасной операцией, выполняемой с тем же URI, из которого было запрошено состояние представления, кеши должны аннулировать любые сохраненные представления для этого URI. Однако, в зависимости от конструкции вашего сервера, это может привести к тому, что нежелательные «пустые» черновики будут по-прежнему доступны. Однако эта операция по-прежнему удовлетворяет идемпотентным требованиям. При повторной отправке запроса эффективный результат должен быть одинаковым для каждого запроса, «пустой» ресурс.

Поскольку POST является универсальным инструментом HTTP, обрабатывая запрос в соответствии с собственной семантикой ресурса. , вы можете использовать его как хотите. Однако, если вы используете другой URI, поэтому отправьте этот запрос вам, возможно, возникнут те же проблемы с кешированием, которые возникают при PATCH.

WebDAV указывает идемпотентную, но небезопасную операцию MOVE, которую также можно найти в реестре HTTP-методов IANAs . Этот метод делает то, что предполагает его название. If перемещает целевой ресурс в место назначения, выполняя этап копирования, за которым следует этап поддержания согласованности, который заканчивается этапом удаления целевого ресурса. Эти три шага также будут выполняться атомарно. Запрос здесь выглядит так, предполагая те же самые URI, указанные выше.

MOVE /configurations/drafs/eaff31bd-5291-4287-a7dd-fbe5b1e47b67
Host: www.acme.com
Destination: /configurations/approved/eaff31bd-5291-4287-a7dd-fbe5b1e47b67

...

Поскольку эта операция небезопасна, любое кешированное представление будет автоматически аннулировано.

Другая возможность - не раскрывать состояние конфигурации в отображении URI, но сохраните его в самом ресурсе. Это также будет работать только с одним и тем же URI для самой этой конфигурации. Внутри вам нужно будет сохранить текущую активную конфигурацию, а также любую черновую версию в одном и том же ресурсе. Обратной стороной здесь является то, что вы в основном отправляете намного больше данных в одном ответе, то есть сохраненную текущую версию и всю допустимую черновую версию. Вы можете ввести определенные фильтры, чтобы получать только принятые, отклоненные или ожидающие конфигурации. Формат представления, для которого возвращается полезная нагрузка, возможно, должен поддерживать клиент, чтобы легко идентифицировать здесь текущую и черновую версии.

Тогда возникает вопрос: как обрабатывать случай редактирования для утвержденная конфигурация, которая должна создать ожидающую конфигурацию.

В случае JSON патча вы можете попробовать что-то вроде этого:

PATCH /configurations HTTP/1.1
Host: www.acme.com
Content-Type: application/json-patch+json; charset="utf-8"
ETag: 33a64df551425fcc55e4d42a148795d9f25f89d4
...

[
  { 
    "op": "copy", 
    "from": "/approved/eaff31bd-5291-4287-a7dd-fbe5b1e47b67", 
    "path": "/drafts/eaff31bd-5291-4287-a7dd-fbe5b1e47b67" 
  },
  {
    "op": "replace",
    "path": "/drafts/eaff31bd-5291-4287-a7dd-fbe5b1e47b67/field1",
    "value": "new value"
  },
  ...
]

, который сначала создает копию текущая утвержденная версия конфигурации, а затем приступает к ее редактированию. Требование atomi c к PATCH гарантирует, что будут применены все или ни одно из изменений. это то, как можно обновить состояние ресурса. Такое представление будет содержать необходимые поля, предварительно заполненные текущим состоянием, что позволяет пользователю быстро изменить состояние ресурса. Поскольку редактирование утвержденного ресурса должно сначала напоминать создание чернового ресурса, сервер должен знать об этом и уже проинструктировать клиента отправить запрос PUT в черновую конечную точку, а не на исходную одобренную конечную точку. После обработки ответа на стороне обслуживания ему просто нужно выяснить, доступен ли контент или пустая полезная нагрузка, чтобы решить, был ли черновик отредактирован или принят / отклонен.

Через POST вы можете делать все, что вы хотите, поэтому я не думаю, что вам нужны объяснения в этом случае ...

При использовании методов WebDAV вам, к сожалению, может потребоваться разделить инструкции на несколько. COPY будет, как следует из названия, скопировать целевой ресурс в какое-то место, определенное в заголовке Destination. После этого вы можете просто отредактировать этот файл. Если сравнивать его с типичным веб-взаимодействием, ресурс может быть скопирован уже после того, как пользователь щелкнет кнопку редактирования. Ответ на нажатие кнопки редактирования будет представлять собой представление формы, содержащее предварительно заполненные данные скопированного ресурса, который при нажатии кнопки отправки просто выполняет регулярное обновление ресурса в черновике ресурса. Однако эту модель взаимодействия необходимо сопоставить с более общим c уровнем. Хотя концепции остались прежними. Сначала клиент должен заявить о своей заинтересованности в редактировании уже утвержденной конфигурации, что приводит к созданию копии в пространстве черновика и последующему возврату представления формы, позволяющего приложению поддерживать своего пользователя в обновлении данных.

В последнем случае, когда вы сохранили все в одном ресурсе, для создания нового черновика при "редактировании" принятой конфигурации требуется только добавить эту измененную версию в набор черновиков. Сервер должен сравнить текущую конфигурацию с той, что предоставлена ​​в запросе, и если они отличаются, предоставленную полезную нагрузку необходимо добавить в черновики.

Как видите, у вас есть несколько возможностей, которые вы можете выбрать из. Хотя исправление кажется хорошим выбором, оно не coop хорошо работает с кешированием, а также зависит от согласованного типа носителя. PUT требует некоторого «изменения правил», хотя потенциально может быть использован для выполнения работы, а также для аннулирования любого сохраненного представления кэша. POST - это универсальная операция общего назначения, которую можно использовать буквально для всего, что вам нужно или нужно. И последнее, но не менее важное: редизайн ваших конфигураций и черновиков в один ресурс также может работать.

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