Pull to refresh

Comments 25

А-а! ColdFusion.
Неужели его кто-то использует?

А за статью по AngularJS спасибо.
Статья с осени прошлого года :-) По ресурсам больше ничего не смог найти.
Поправьте, если я ошибаюсь, но RESTful подразумевает использование методов GET, POST, PUT, DELETE и указание действия в параметрах запроса, а не в адресе ресурса.
DELETE /api.cfm/messages
POST /api.cfm/messages/8?action=archive
Можно подробнее об этом. И желательно ссылку на правила (укажу в примечании). Т.к. это перевод, то что было в оригинале, то было
Я погорячился, сказав слово «подразумевает» — как справедливо заметил marapper: REST — это принцип построения архитектуры, строгой спецификации не существует. Зато существует куча руководств в стиле best practices — сегодня только ленивый (вроде меня) не написал собственный гайд по «правильному» REST.

Мне по душе пришлись ресурсы restapitutorial.com (и их RESTful Best Practices), и Thoughts on RESTful API Design.
Как указывать действие в запросе — руководства оставляют решение этого вопроса на плечах разработчика.
Ох уж все эти бест практисы. Выбрали бы уже один, пусть не бест, а норм и все бы им пользовались. А так только голову забивают))
Не совсем, REST — просто архитектура, она определяет использование возможностей протокола, т.е.

Метод как указание типа действия (фетчинг, изменение имеющегося, создание нового, удаление). Есть еще PATCH, HEAD — их также можно использовать.

Ресурс как объектное отражение сущностей, над которым можно произвести какие-то действия.

Коды и прочие заголоки запросов и ответов как дополнительная возможность управления и доп.информация.

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

Также есть такая вещь, как HateOAS, штука которая, кхе-кхе, гомогенизирует такой REST-интерфейс — restcookbook.com/Basics/hateoas/
Как понял, они (HateOAS) просто-напросто все действия в GET'е проводят. И все равно называют это REST'ом :-)
Наверное, у меня не совсем верное представление о понятии «RESTful» — я думаю, что это просто набор лучших практик реализации REST-архитектуры, и в первую очередь — использование по полной возможностей протокола HTTP.

На самом деле, я считаю, что указывать действие стоит вообще в http-заголовках, а не параметрах URI — но уж лучше в параметрах, чем в пути.
Но, если над сущностью можно сделать больше операций, чем обычно, то куда логичнее это сделать отдельным ресурсом, т.к. смешение в POST редактирования и, например, привязки другой сущности — странно.
Вы не хотите смешивать в одном методе привязку сущности и редактирование, а я не хочу смешивать в ресурсе сущность и действия. Метод POST просто подразумевает отправку данных, ничего более, на то он и метод. Кто-то вообще отождествляет метод POST с созданием сущности — не думаю, что это правильно. А для привязки сущности есть http-метод LINK :)
А что по этому поводу говорят реализации REST в популярных серверных фреймворках? Они же предлагают какой-то путь? Или просто расчленяют запрос на параметры, а дальше сам думай?
Не уверен, что совсем понял вопрос, но:
есть python-фреймворки flask и bottle — каждый из них позволяет повесить на один маршрут обработчики для разных http-методов: bottle с помощью декораторов, flask — c помощью декораторов, либо с помощью отдельных методов объекта, представляющего ресурс.
Ну а работа с http-заголовками и аргументами запроса не представляет труда во многих популярных фреймворках.
> POST /api.cfm/messages/8?action=archive
Я читал где то, что если Вы делаете POST и передаете
параметр action это почти всегда плохо. И в целом
уже несколько лет такое правило мне здорово помогает.

Лучше делать POST /api.cfm/archive и в теле запроса message=8
В ответ сервер возвращает ID транзакции по которому можно
опрашивать состояние операции.
Я читал где то, что если Вы делаете POST и передаете
параметр action это почти всегда плохо.
Речь о параметре в URI, или вообще в запросе?
И в целом
уже несколько лет такое правило мне здорово помогает.
Помогает чем?
Лучше делать POST /api.cfm/archive и в теле запроса message=8
В случае с добавлением в архив это может быть уместно, но что делать если нужно просто произвести манипуляцию над документом? Например, конвертировать все изображения документа в формат png, указав при этом необходимые характеристики конечного изображения.
В ответ сервер возвращает ID транзакции по которому можно
опрашивать состояние операции.
Такой подход актуален для операций, которые могут затянуться по времени. Для быстрых операций, на мой взгляд, это избыточное решение.
> Помогает чем?
Помогает поддерживать API в постоянно изменяющихся условиях.
Смотришь на решения которые принимал несколько лет назад и
видишь — такой подход хорош. С точки зрения клиенской библиотеки
и с точки зрения структуры исходного кода. Позольте объяснить подробней.

Очень редко операции по изменению данных касаются одного ресурса.
Обычно изменения происходят в рамках одной транзакции.
Вот мы эту транзакцию и создаем делая POST.

Ведь если нужно изменить одно поле — делаем PUT, не так ли?

> Речь о параметре в URI, или вообще в запросе?
В запросе. Хотя даже /item/id/do-something я тоже стараюсь избегать.
Наверное потому что потратив много времени в борьбе с чужими API
и на разработку своих, считаю Computation REST наиболее близким к идеалу.

Но нужно понимать что правило «don't do POST with action» это не догма, а способ
сделать жизнь простого разработчика проще. Который работает для меня.

PS. www.erenkrantz.com/CREST/
Потихоньку начинаю понимать плюсы такого подхода.
Спасибо за информацию для размышления.
Спасибо за понимание. Больше хороших API!
Зачем использовать два «контроллера» в url?
На сколько я помню, достаточно вот такого:
......
"./api.cfm/messages/:id/:docController"
......
                clear: {
                            method: "POST",
                            params: {
                                docController: "clear-all"
                            }
                        },

И anular Отлично отследит отсутвие :id, и составит правильный url
Хотите сказать, что команду «arhive» так же передавать в docController, а Ангуляр просто уберет лишний слеш (возникающий из-за отсутствующего айди)?
И при этом получается более логично.
message.archive({id: 8}); // архивация сообщения с id=8
message.archive(); // архивация всех сообщений
Вообще, да. В статье есть фраза, которую перевел как «Пока использую только один из них, в то время, как Ангуляр построит RESTful-ресурс должным образом» Возможно, автор имел в виду такой подход… Просто затруднился правильно подобрать смысл.
Если я правильно понял, то в оригинале говорится о вот этих двух параметрах ":listController:id", из которых angular построит правильный запрос.
Не понимаю почему автор оригинала выбрал такой подход… но всё равнно узнал что-то новое. Я до этого даже и не думал, что можно использовать совместно несколько плейсхолдеров, в одной части url.
На сколько я понял REST, то смысл в том, что бы манипулировать самими данными, без вызова функций обработки на стороне сервера.

archiveMessage = function(id) {
  message.id = id;
  message.$save();
}
archiveAll = function() {
  //Update field loop
  ....
  // end loop
  var MyRequest = $resource('/messages', {}, {saveData: {method:'POST', isArray: true}}); 
  $scope.doSubmit = function() { MyRequest.saveData({}, $scope.data); //scope.data is array of objects
}

Да согласен, чрезмерная передача данных будет (+ еще нужно учесть, что результат сохранения в REST должен вернуть объект измененный/массив объектов)
/messages/:listController:id/:docController не будет работать если hostname или часть пути содержит `id`.

Например:

$resource('http://foo-id.com/messages/:listController:id/:docController', {id: 2});

Выдаст

foo-id.com/messages:listController2
Only those users with full accounts are able to leave comments. Log in, please.