Какой метод HTTP использовать с REST API, если у нас есть родительско-дочерние объекты, а родительский объект уже создан? - PullRequest
0 голосов
/ 07 мая 2019

Я посмотрел на этот вопрос PUT против POST и другие вопросы по stackoverflow и после просмотра ответов, которые я обнаружил:

Используйте POST, если сервер идентифицирует адресресурс

Используйте PUT, если клиенту известен адрес ресурса.

Теперь выше работает нормально, если у меня есть один независимый объект.Например, если у меня есть сущность Student, я допускаю нового ученика в школы, я могу создать конечную точку REST как /api/schools/schools-name/student с POST HTTP-методом.Но как только студент зачислен и мне нужно внести изменения в него, я могу использовать Patch / PUT.

Но в моем случае у меня есть зависимые объекты, которые являются родительскими и дочерними.Сначала я создаю родительскую сущность, используя POST.Теперь дочерняя сущность создается только после того, как родительская сущность была создана.Почему они не могут быть созданы вместе, как после создания родительского объекта, так и создания дочернего объекта, из-за бизнес-требований.

Важно отметить, что родительский и дочерний объект связаны только столбцом id.,Поэтому в настоящее время мой URL для создания дочерней сущности - /api/entities/parent-entity-id.Также нет тела запроса при создании дочерней сущности, так как вся необходимая информация для создания хранится в родительской сущности.

Мой вопрос заключается в том, должен ли этот метод быть POST, когда мы создаем дочернюю сущность илиPUT, как я обновляю дочерние элементы родительской сущности, которая уже была создана?

Ответы [ 4 ]

1 голос
/ 07 мая 2019

Как уже упоминалось в вопросе, нет тела запроса для создания дочерней сущности. Этот API просто для запуска создания дочернего объекта. У родительской сущности уже есть вся информация.

Если вы отправляете на сервер запрос небезопасный , и он не соответствует семантике любого из других методов HTTP, вам следует использовать POST.

В частности, если тело сообщения не является представлением-кандидатом для ресурса, идентифицированного target-uri, тогда PUT выходит за пределы.

Метод PUT запрашивает, чтобы состояние целевого ресурса было создано или заменено на состояние, определенное представлением, заключенным в полезную нагрузку сообщения запроса

0 голосов
/ 07 мая 2019

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

REST сильно зависит от стандартизированных протоколов и типов носителей.Модель взаимодействия очень похожа на просматриваемую сеть Web, двоюродного брата REST.Следовательно, те же понятия, которые применимы к сети, также применимы к REST.Основная идея в обоих случаях должна заключаться в том, что сервер учит клиента тому, как что-то делать, в то время как клиенты берут только то, что им дают, не пытаясь получить дополнительные знания из предыдущего взаимодействия или анализа URI или тому подобного.То есть в Интернете HTML-формы используются, чтобы позволить клиентам вводить определенный ввод, который отправляется на сервер после нажатия кнопки отправки.Как целевой URI, так и используемый метод включены в эту веб-форму, поэтому клиенту на самом деле не нужен этот факт.Благодаря наличию элемента кнопки клиент также неявно знает, что можно нажать кнопку и, как следствие, могут быть выполнены определенные действия.Те же понятия, которые используются в Интернете, теперь должны использоваться между приложениями для взаимодействия друг с другом.Здесь либо HTML-формы могут быть использованы повторно, либо должны быть разработаны определенные, специализированные медиа-типы (например, hal-form ).Посредством согласования типа контента клиент и сервер могут на самом деле договориться о формате представления и о поддержке, и, следовательно, избежать проблем взаимодействия.

Одна распространенная проблема, с которой, похоже, сталкиваются многие разработчики REST, - это думать, что конечные точки REST возвращают определенные данные вбыть определенного типа, то есть данные сотрудника компании или элементы определенной иерархии. Fielding утверждает, что вместо введения набранных ресурсов , значимых для клиента, REST API должны тратить почти все свои описательные усилия на определение типа носителя (s) используется для представления ресурсов и определения состояния приложения или для определения расширенных имен отношений и / или разметки с поддержкой гипертекста для существующих стандартных типов носителей .

Еще одна вещь, упомянутая здесь, которую яв моем комментарии уже есть полосатость: URI по умолчанию не наследуют отношения родитель-потомок.URI в целом, включая любые параметры пути, матрицы и / или запроса, представляет собой просто ссылку на ресурс и может рассматриваться как ключ, используемый для кэшей для возврата тела ответа, ранее сохраненного для этого ключа (= URI).Поэтому клиенты не должны пытаться получить семантические знания из самих URI, а просто использовать отношения ссылок, возвращаемые для таких URI.Это позволяет серверам заменять URI в будущем, в то время как клиенты по-прежнему могут вызывать их на основе имени, для которого был возвращен URI.

Поскольку сами URI не передают никакой семантической информации, они не могут на самом деле выразить родителя.-детские отношения самостоятельно.Мы, люди, склонны интерпретировать URI, такой как /api/company/abc/employee/123, как выражение того, что сотрудник с номером 123 работает на компанию abc, что может быть правдой, но также не должно быть, как объяснено ранее, URI не имеют семантическойвыражать такие вещи.Только с помощью набора таких URI можно создать такое семантическое дерево.

Но в моем случае у меня есть зависимые объекты, которые являются родительскими и дочерними.Сначала я создаю родительскую сущность, используя POST.Теперь дочерняя сущность создается только после того, как родительская сущность была создана.

Если вы присмотритесь к HTTP-методам , вы можете увидеть, что POST-запросы обрабатываются в соответствии с определенной семантикой ресурса, что означает, что вы буквально можете выполнять все, что у вас естьсюда.Это де-факто швейцарский армейский нож в вашем наборе инструментов, и его следует использовать, если другие методы не соответствуют вашему сценарию использования.

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

Ни методы HTTP, ни URI не могут создавать такие семантические отношения между родительскими и дочерними ресурсами.Тем не менее, это то, для чего существуют отношения ссылок!Связи - это ребра между двумя объектами, которые дают имя контексту отношений между этими двумя объектами.Такие отношения ссылок должны быть стандартизированы , в соответствии с общими соглашениями или представляют типы расширений, как определено в RFC 5988 (веб-ссылки) , чтобы способствовать их повторному использованию.К сожалению, однако, IANA напрямую не указывает отношение ссылки parent и child.up может использоваться для ссылки от ребенка к родителю в дереве.Однако с помощью механизма расширения это относительно легко получить, то есть http://api.acme.com/rel/parent и http://api.acme.com/rel/child или что-то подобное.

Следующий бит, который нужно обсудить в цитируемом сегменте исходного сообщения, произойдет до семантикисоздание родительского в отличие от дочернего ресурса.HTTP не имеет какой-либо семантики транзакций или гарантий упорядочения запросов, кроме указанных в разделе конвейерной обработки *1056*, который в любом случае применяется только к безопасным методам.Поэтому HTTP не дает никаких обещаний по обработке запросов, так как они либо вообще не достигают сервера, либо ответ просто теряется по какой-либо причине.Только если клиент получает ответ 201 Created, включающий заголовок Location, указывающий на созданный ресурс, клиент точно знает, что ресурс создан, и только в соответствии со спецификацией клиенту разрешается создавать дополнительный дочерний ресурс.

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

Важно отметить, что родительский и дочерний объекты связаны только столбцом id.Поэтому в настоящее время мой URL для создания дочерней сущности - / api / entity / parent-entity-id.Также нет тела запроса при создании дочерней сущности, так как вся необходимая информация для создания хранится в родительской сущности.

REST фактически не заботится о вашей доменной модели.Здесь у вас есть классический пример ресурсов /persons, где три человека могут быть идентифицированы с помощью отдельных отличительных URI, таких как /persons/alice, /persons/bob и /persons/joe.Мы ничего не знаем о фактических данных, возвращаемых какой-либо из этих конечных точек на самом деле, и, как уже упоминалось выше, вы не можете напрямую определить из URI, чей родитель которого (или что любой из URI фактически представляет человеканачать с).Через связь ссылок теперь можно задавать такую ​​структуру контекста, заявляя, что Боб и Алиса являются родителями Джо, а Джо - потомок Боба и Алисы.

Обратите внимание, что в приведенном выше примере фактическое содержание ресурсов не имело значения для клиента. Мы до сих пор не знаем, содержат ли какие-либо ресурсы какую-либо информацию вообще. Все, что мы знаем, это то, что есть 3 доступных ресурса, которые каким-то образом связаны друг с другом. Так что, если цель вашей системы - просто представлять такие отношения, тогда продолжайте. Используйте ссылки между этими ресурсами, чтобы клиенты могли искать эти отношения, если они заинтересованы. Если клиент интересуется подробностями ресурса, он все равно отправит запрос на определенный набор типов медиа на сервер. Обнаружение и исследование - две общие вещи, которые вы хотите гарантировать в экосистеме REST.

У меня вопрос, должен ли этот метод быть POST, когда мы создаем дочернюю сущность, или PUT, когда я обновляю дочерние элементы родительской сущности, которая уже была создана?

AS POST - это универсальный инструмент, который необходимо использовать, если другие методы не подходят, использование POST, безусловно, не является неправильным. Если вы присмотритесь к другим методам, то увидите, что они служат разным целям, т. Е. PUT имеет семантику замены текущего содержимого на то, которое указано в полезной нагрузке запроса. Поэтому он выражает другой вариант использования, чем вы на самом деле хотите IMO. Таким образом, вы должны придерживаться POST также для создания своих детей.

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

Этот пост, вероятно, уже намного длиннее, чем нужно, хотя я хочу убедиться, что вы понимаете смысл REST и когда его использовать. Если вам действительно не нужна система, требующая таких свойств, как свобода для развития , отказоустойчивость и поддержка работы приложения / системы в течение десятилетий , возможно, легче получить либо доступ к вашей собственной службе RPC, либо, возможно, непосредственно к вашей модели данных.

0 голосов
/ 07 мая 2019

Вы создаете новый экземпляр, поэтому вы должны использовать метод POST в конечной точке для ранее созданного родительского экземпляра. Пример:

POST /parent/<parent_id>/children/ 
BODY:
{"json with children data...."}
0 голосов
/ 07 мая 2019

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

Таким образом, это не имеет ничего общего с состоянием ресурса иследовательно, ничего общего с REST.

Вы не ставите новое состояние ресурса, поэтому вам следует избегать использования PUT.

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