Я планирую создать RESTfull API, но есть некоторые архитектурные вопросы, которые создают некоторые проблемы в моей голове. Добавление логики бизнес-процессов для клиентов - это вариант, которого я бы хотел избежать, поскольку обновление нескольких клиентских платформ сложно поддерживать в режиме реального времени, когда бизнес-логика может быстро измениться.
Допустим, у нас есть статья в качестве ресурса (api / article), как мы должны реализовывать такие действия, как публикация, отмена публикации, активация или деактивация и т. Д., Но при этом стараться сделать ее максимально простой?
1) Должны ли мы использовать api / article / {id} / {action}, так как там может происходить много бэкэнд-логики, например, перемещение в удаленные местоположения или изменение нескольких свойств. Вероятно, самое сложное здесь заключается в том, что нам нужно отправить все данные статьи обратно в API для обновления, и многопользовательская работа не может быть реализована. Например, редактор может отправить данные на 5 секунд старше и исправить перезапись, что некоторые другие журналисты только что сделали 2 секунды назад, и я никак не мог объяснить это клиентам, поскольку те, кто публикует статью, на самом деле никак не связаны с обновлением контента.
2) Создание нового ресурса также может быть опцией api / article- {action} / id, но тогда возвращаемым ресурсом будет не article-{action}, а article, в котором я не уверен, правильно ли это. Кроме того, в статье, посвященной классу кода на стороне сервера, выполняется актуальная работа с обоими ресурсами, и я не уверен, противоречит ли это RESTfull.
Любые предложения приветствуются ..
api/article?action=publish
? Параметры запроса предназначены для тех случаев, когда состояние ресурса зависит от упомянутого вами «алгоритма» (или действия). Напримерapi/articles?sort=asc
, действительныйОтветы:
Я считаю полезными описанные здесь методы :
источник
/article/123/deactivations
для создания нового запроса на деактивацию для статьи 123, сервер может не только деактивировать запрошенный ресурс, но и фактически сохранить мой запрос на деактивацию, чтобы я мог получить его статус позже.PUT /gists/:id/star
нетPOST /gists/:id/star
?Операции, приводящие к серьезным изменениям состояния и поведения на стороне сервера, такие как описанное вами действие «публикация», сложно моделировать в REST. Решение, которое я часто вижу, состоит в том, чтобы неявно управлять таким сложным поведением через данные.
Рассмотрите возможность заказа товаров через REST API, предоставляемый онлайн-продавцом. Заказ - сложная операция. Несколько продуктов будут упакованы и отправлены, с вашего счета будет снята оплата, и вы получите квитанцию. Вы можете отменить свой заказ в течение ограниченного периода времени, и, конечно, есть полная гарантия возврата денег, которая позволяет вам вернуть продукты для возврата.
Вместо сложной операции покупки такой API может позволить вам создать новый ресурс, заказ на покупку. Вначале вы можете вносить в него любые изменения: добавлять или удалять продукты, изменять адрес доставки, выбирать другой способ оплаты или вообще отменять заказ. Вы можете сделать все это, потому что вы еще ничего не купили, вы просто манипулируете некоторыми данными на сервере.
После того как ваш заказ на покупку завершен и льготный период истекает, сервер блокирует ваш заказ, чтобы предотвратить дальнейшие изменения. Только в это время начинается сложная последовательность операций, но вы не можете управлять ею напрямую, только косвенно через данные, которые вы ранее поместили в заказ на поставку.
Исходя из вашего описания, «публикация» может быть реализована таким образом. Вместо того, чтобы показывать операцию, вы помещаете копию черновика, который вы просмотрели, и хотите опубликовать его как новый ресурс в / publish. Это гарантирует, что любые последующие обновления в черновике не будут опубликованы, даже если сама операция публикации завершится через несколько часов.
источник
Подобные вещи являются проблемой, независимо от того, что вы делаете, это очень похоже на проблему с распределенным управлением исходным кодом (Mercurial, Git и т. Д.), И решение, записанное в HTTP / ReST, выглядит немного похожим.
Предположим, у вас есть два пользователя, Алиса и Боб, оба работают над ними
/articles/lunch
. (для ясности ответ выделен жирным шрифтом)Во-первых, Алиса создает статью.
Сервер не создал ресурс, потому что к запросу не было прикреплено никакой «версии» (при условии, что
/articles/{id}/{version}
для выполнения создания был создан идентификатор . Алиса была перенаправлена на URL-адрес статьи / версии, которую она будет создавать. Пользователь Алисы). Затем агент повторно применяет запрос по новому адресу.И теперь статья была создана. Далее Боб смотрит на статью:
Боб смотрит туда:
Он решает добавить свои собственные изменения.
Как и в случае с Алисой, Боб перенаправлен туда, где он будет создавать новую версию.
Наконец, Алиса решает, что она хотела бы добавить к своей собственной статье:
Вместо перенаправления в обычном режиме клиенту возвращается другой код состояния
409
, который сообщает Алисе, что версия, из которой она пыталась перейти, уже разветвлена. Новые ресурсы были созданы в любом случае (как показано вLocation
заголовке), и различия между ними были включены в тело ответа. Алиса теперь знает, что запрос, который она только что сделала, нужно как-то объединить.Все это перенаправление связано с семантикой
PUT
, которая требует, чтобы новые ресурсы создавались именно там, где запрашивает строка запроса. это также могло бы сохранить цикл запроса, используяPOST
вместо этого, но тогда номер версии должен был бы быть закодирован в запросе каким-то другим волшебством, которое мне показалось менее очевидным для целей иллюстрации, но, вероятно, все еще было бы предпочтительным в реальном API минимизировать циклы запроса / ответа.источник
Вот еще один пример, который касается не содержимого документов, а скорее переходного состояния. (Я нахожу управление версиями - учитывая, что, как правило, каждая версия может быть новым ресурсом - своего рода легкая проблема.)
Допустим, я хочу предоставить сервис, работающий на машине, через REST, чтобы его можно было остановить, запустить, перезапустить и т. Д.
Какой подход RESTful здесь? POST / service? Команда = перезагрузка, например? Или POST / сервис / состояние с телом, скажем, «работает»?
Здесь было бы неплохо систематизировать лучшие практики и определить, является ли REST правильным подходом к подобным ситуациям.
Во-вторых, давайте предположим, что я хочу запустить какое-либо действие из службы, которое не влияет на его собственное состояние, а скорее вызывает побочный эффект. Например, служба почтовой рассылки, которая отправляет отчет, созданный во время звонка, на несколько адресов электронной почты.
GET / report может быть способом получения копии отчета самостоятельно; но что, если мы хотим подтолкнуть на сторону сервера дальнейшие действия, такие как отправка электронной почты, как я сказал выше. Или запись в базу данных.
Эти случаи танцуют вокруг разрыва между ресурсами и действиями, и я вижу способы обращаться с ними REST-ориентированным способом, но, честно говоря, это похоже на хакерство. Возможно, ключевой вопрос заключается в том, должен ли REST API поддерживать побочные эффекты в целом.
источник
REST ориентирован на данные, и такие ресурсы лучше всего работают как «вещи», а не действия. Неявная семантика http-методов; GET, PUT, DELETE и т. Д. Служат для усиления ориентации. POST, конечно, является исключением.
Ресурс может быть смесью данных, т.е. содержание статьи; и метаданные т.е. опубликовано, заблокировано, редакция. Есть много других возможных способов срезать данные, но сначала вам нужно будет посмотреть, как будет выглядеть поток данных, чтобы определить наиболее оптимальный (если он есть). Например, может случиться так, что редакции должны быть их собственным ресурсом согласно статье, как предлагает TokenMacGuy.
Что касается реализации, я бы, вероятно, сделал что-то вроде того, что предлагает TockenMacGuy. Я бы также добавил поля метаданных в статью, а не ревизию, например «заблокирован» и «опубликован».
источник
Не думайте, что это напрямую манипулирует состоянием статьи. Вместо этого вы помещаете заказ на изменение, запрашивая создание статьи.
Вы можете смоделировать помещение заказа на изменение как создание нового ресурса заказа на изменение (POST). Есть много преимуществ. Например, вы можете указать будущую дату и время, когда статья должна быть опубликована как часть порядка изменений, и позволить серверу беспокоиться о том, как это реализовано.
Если публикация - это не мгновенный процесс, вам не нужно ждать его завершения, прежде чем вернуться к клиенту. Вы просто подтверждаете, что заказ на изменение был создан, и возвращаете идентификатор заказа на изменение. Затем вы можете использовать URL-адрес, соответствующий этому порядку изменений, чтобы поделиться статусом этого заказа.
Ключевым моментом для меня было признание, что метафора порядка изменений - это просто еще один способ описания объектно-ориентированного программирования. Вместо ресурсов мы называем объекты. Вместо того, чтобы менять порядок, мы называем их сообщениями. Один из способов отправить сообщение от A к B в OO - это вызвать A для вызова метода на B. Другой способ сделать это, особенно когда A и B находятся на разных компьютерах, это заставить A создать новый объект, M и отправить его Б. ОТДЫХ просто формализует этот процесс.
источник
Если я вас правильно понимаю, я думаю, что то, что у вас есть, является скорее вопросом определения «бизнес-правила», чем технической проблемой.
Тот факт, что статья может быть перезаписана, может быть решен путем введения уровней авторизации, где старшие пользователи могут переопределять версии младших пользователей. Также путем введения версий, а также столбца для отображения состояния статьи (например, «в разработке», «окончательный вариант»). и т. д.), вы могли бы преодолеть это. Вы также можете дать пользователю возможность выбрать данную версию либо по комбинации времени подачи, либо по номеру версии.
Во всех вышеперечисленных случаях вашей службе необходимо реализовать установленные вами бизнес-правила. Таким образом, вы можете вызвать службу с параметрами: идентификатор пользователя, статья, версия, действие (если версия является необязательной, опять же, это зависит от ваших бизнес-правил).
источник