REST vs SOAP. Часть 1. Почувствуйте разницу

Некоторое время назад я гуглил интернет по поводу “REST vs SOAP”, прочитал пару статей и вроде бы все понял, но не почувствовал от этого никакого удовлетворения. Что-то было не так, то ли я не почувствовал основную идею, то ли просто читал, одновременно слушая новый музон и думая о новой фиче в проекте. Как появилось время, решил восполнить этот пробел, заодно написав полезную статью по этому поводу.

Оглавление цикла статей:


REST vs SOAP. Часть 1. Почувствуйте разницу.
REST vs SOAP. Часть 2. Как проще и эффективнее организовать общение платформ?

Пару месяцев назад при беглом изучении вопроса я понял о REST примерно следующее:
  • Все является ресурсами с уникальным идентификатором (URL)
  • Все операции клиента с сервером stateless, т.е. сервер не должен хранить вообще никакой информации о клиенте – никакой сессии
  • Все запросы можно поделить на 4 типа в соответствии с CRUD, причем каждому типу сопоставляется HTTP метод – Post, Get, Put и Delete
  • Вся логика крутится вокруг ресурсов, а не операций

Вот с такими воспоминаниями я начал бороздить просторы интернета. Первой мыслью было, а почему выбрано название REST? Representational State Transfer, в переводе википедии «передача состояния представления»… Никакой картинки в голове не вырисовывается даже при четвертом вчитывании. Здесь пытаются ответить на мой вопрос и даже приводят то, как Рой Филдинг (человек, сформулировавший принципы REST) сам объяснял происхождение названия. Мысль сводится к тому, что запрос ресурса с сервера переводит клиентское приложение в определенное состояние (state), а запрос следующего ресурса меняет состояние приложения (transfer). А “Representational” означает то, что ресурс возвращается не просто так, а в каком-то представлении, например в представлении для машины или в представлении для человека. Сложно, как по мне, и сбивает с толку, т.к. состояние – это как раз то, что отсутвует в отношениях клиент-сервер в архитектуре REST. Я бы назвал как-то вроде «Стандартизированное оперирование данными», вот только сначала надо что-то придумать, а потом уже яркое название выбирать. А Филдинг в своей диссертации признается, что название придумано не для того, чтобы было понятно, о чем речь, а «is intended to evoke an image of how a well-designed Web application behaves». Но это ничего, не будем обижаться на уважаемого человека, мы тоже в дипломных работах часто формулировали все так, чтобы было как можно непонятнее и нельзя было придраться. Нашлась и неплохая формулировка идеи по-русски – «представление данных в удобном для клиента формате». Справедливости ради надо отметить, что пока я формулировал свои доводы о нелогичности названия, я увидел в нем некоторую логику, по крайней мере в английском варианте.

Важно понимать, что REST – это не протокол и не стандарт, а архитектурный стиль. У этого стиля есть свои принципы. Позволю себе скопировать их с понравившегося источника и прокомментировать:
  1. Give every “thing” an ID.
    Очччень желательно.
  2. Link things together.
    Например, в страницу (представление) о Mercedes C218 хорошо бы добавить ссылку на страницу конкретно о двигателе данной модели, чтобы желающие могли сразу туда перейти, а не тратить время на поиск этой самой страницы.
  3. Use standard methods.
    Имеется в виду, экономьте свои силы и деньги заказчика, используйте стандартные методы HTTP, например GET
    http://www.example.com/cars/00345
    для получения данных вместо определения собственных методов вроде getCar?id=00345.
  4. Resources can have multiple representations.
    Одни и те же данные можно вернуть в XML или JSON для программной обработки или обернутыми в красивый дизайн для просмотра человеком.
  5. Communicate statelessly.
    Да, RESTful сервис должен быть как идеальный суд – его не должно интересовать ни прошлое подсудимого (клиента), ни будущее – он просто выносит приговор (отвечает на запрос).

Только что употребленный термин RESTful (веб-)сервис всего лишь означает сервис, реализованный с использованием принципов REST. Так что же нам дает следование этим самым принципам REST? Для начала я бы назвал простоту основным преимуществом архитектуры REST. Простоту идеи, простоту разработки и добавления функциональности к RESTful приложениям. Идея настолько проста и универсальна, что ее даже сложно сначала уловить. Мы не добавляем никакого нового слоя в наш и без того многослойный программерский пирог, а просто используем уже давно признанные стандарты. Поэтому чтобы ответить на вопрос о преимуществах и недостатках и чтобы анализ имел больше смысла, предлагаю перейти к сравнению подходов SOAP и REST.

  1. SOAP – это целое семейство протоколов и стандартов, откуда напрямую вытекает, что это более тяжеловесный и сложный вариант с точки зрения машинной обработки. Поэтому REST работает быстрее.
  2. SOAP используют HTTP как транспортный протокол, в то время как REST базируется на нем. Это означает, что все существующие наработки на базе протокола HTTP, такие как кеширование на уровне сервера, масштабирование, продолжают так же работать в REST архитектуре, а для SOAP необходимо искать другие средства. Взамен этого SOAP сервисы получают такое мифическое свойство, как возможность работать с любым протоколом транспортного уровня вместо HTTP, однако практической пользы от него зачастую не больше, чем сотрудникам Челябинского трубопрокатного завода от большого количесва статей в википедиях на мертвых языках.
  3. Есть мнение, что разработка RESTful сервисов намного проще. Наверное, это правда, если использовать Notepad в качестве основной среды разработки, но вот с использованием наших чудесных средств разработки, я позволю себе усомниться в верности этого утверждения.
  4. В первом гугловском результате по запросу «REST vs SOAP» акцентируется внимание на том, что ответ REST может быть представлен в различных форматах, а SOAP привязан к XML. Это действительно важный фактор, достаточно представить себе вызов сервиса из javascript, ответ на который мы определенно хотим получать в JSON.
  5. «REST vs SOAP» можно перефразировать в «Простота vs Стандарты», что проявляется в том, что для SOAP мы имеем протокол WSDL для исчерпывающего описания веб-сервиса, который с использованием все тех же чудесных средств разработки прото-таки волшебным образом делает почти всю работу за нас. Со стороны REST мы имеем загадочный и неиспользуемый протокол WADL, который, в принципе, и не нужен – он мешает простоте.
  6. Второй аспект предыдущего пункта – обработка ошибок. В SOAP она полностью стандартизована, а REST может использовать давно известные коды ошибок HTTP (если здесь Вас посетила мысль, что это же очевидно и зачем я это пишу, то значит Вы внимательно читаете статью).
  7. То, с чего можно было бы начать, но я припас напоследок. Это одна из ключевых мыслей. SOAP работает с операциями, а REST – с ресурсами. Этот факт в совокупности с отсутствием клиентского состояния у RESTful сервисов приводит нас к тому, что такие вещи как транзакции или другая сложная логика должна реализовываться «SOAP-но».

Приведу пару примеров на понимание разницы между подходами. Букмекерская контора заказала сервис для работы с футбольной статистикой. Пользовательский функционал – получить список матчей, получить детали о матче. Для редакторов – редактировать (Create, Edit, Delete) список матчей, редактировать детали матча. Для такой задачи однозначно надо выбирать подход REST и получать бенефиты от его простоты и естественности во взаимодействии с HTTP. Не нужны нам здесь SOAP-конверты, SOAP-главпочтамты и SOAP-авиапочта, которая может использовать любую марку самолета. Нам всего лишь надо реализовать следующее:



Все очень просто! Теперь пример посложнее. Та же букмекерская контора захотела API для ставок на live матчи. Эта процедура включает в себя многочисленные проверки, например, продолжает ли ставка быть актуальной, не изменился ли коэффициент, не превышена ли максимальная сумма ставки для маркета. После этого происходит денежная транзакция, результаты которой записываются в основную и в резервные базы данных. Лишь после этого клиенту приходит ответ об успешности операции. Здесь явно прослеживается ориентация на операции, имеются повышенные требования к безопасности и устойчивости приложения, поэтому целесообразно использовать SOAP.

И еще пару задач для того, чтобы почувствовать тему:


  • Футбольный клуб заказывает CMS для подробных сведений об игроках команды-неприятеля. Нужен функционал добавления характеристик игрока простыми пользователями прямо во время матча с последующей интеграцией с табло стадиона, на котором необходимо в реальном времени отображать комментарии.
  • Мексиканский наркобарон Педро Гонсалес заказывает API для учета продаж героина в Юго-Западных штатах США. Он особо просит мобильное приложение под эту задачу, т.к. его бизнес часто проходит на открытом воздухе, где нету других вариантов выхода в сеть.
  • Анонимный миллиардер очень хочет такую программу, которая бы ему показывала всех его любовниц в городе, в котором он сейчас находится и то, какой текущий статус отношений. Он хочет интегрировать эту программу с уже существующим его личным десктопным приложением для подбора мест для отдыха, он очень хочет большую красную надпись о возможных неприятностях в окошке, где предлагаются варианты авиаперелета.


Какие подходы Вы бы использовали в данных задачах?

Хотел я еще написать про то, что это все дает .NET разработчику и как это использовать в своих целях, однако вижу, что индекс нудности статьи приближается к критическому, поэтому буду закругляться. С целью понижения все того же показателя я намеренно избегал аспектов безопасности и, например, ответа на вопрос ”А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?”.

А выводы статьи будут следующими:
  1. Филдинг со своими принципами REST ничего не изобрел, а просто собрал в одну диссертацию то, что уже существовало в каком-то виде и изложил то, как можно получать максимальную выгоду из уже сформировавшейся архитектуры сети.
  2. SOAP и REST – не конкуренты. Они представляют разные весовые категории и вряд ли найдется задача, для которой будет сложно сказать, какой подход рациональнее использовать – SOAP или REST. Поэтому «религиозные» убеждения в вопросах выбора архитектуры для веб-сервиса вряд ли будут полезны. Для тех, кто не знает, с чего начать анализ задачи, могу порекомендовать эту презентацию. У них чаще побеждает REST.
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 101
  • 0
    Вот это отсутствие стандартизации на контракт севиса, очень напрягает. То есть вы должны еще убедить всех людей, почему не нужен SOAP и ак быть в случае выставления рест-сервиса кому-нибудь.
    • 0
      По пункту 3 сравнения — а что не устраивает?
      • 0
        я защищаю SOAP в том пункте. Говорю, что например в .Net сложность разработки сопоставимая.
      • +5
        Ровно 2 года назад написал свои соображения на этот счет: «Дао Вебсервиса. (Или да хватит же изобретать велосипеды!)».
        • –8
          18 ноября и 27 октября :) Равенство у вас какое то необыкновенное :)
          • +29
            Я округлил :)

            Можно было написать — «два года назад, так же под конец осени, когда уже чувствуется дуновение приближающейся зимы, воздух в облетевших кронах деревьев прозрачен и зво́нок, но нет еще той промозглости, нагоняющей депрессию на утонченное сознание программиста и писателя, меня посетила гениальная мысль касательно веб-сервисов» :))
            • +9
              Мы много хорошего потеряли из-за таких ваших округлений, похоже.
          • 0
            очень неплохая статья, рекомендую
          • +8
            Все-таки очень бы хотелось увидеть ответ на вопрос
            ”А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?”
            • 0
              Cookies или https.
              • 0
                HTTPS только с шифрованием поможет. При чем здесь авторизация?
                Cookies нарушает принцип Stateless — серверу надо хранить связь этого Cookies с конкретным пользователям.
                А Basic HTTP уже в идеологию REST укладывается
                • +2
                  >> HTTPS только с шифрованием поможет.

                  Правда?
                  Например — www.opennet.ru/base/sec/ssl_cert.txt.html

                  >> Cookies нарушает принцип Stateless — серверу надо хранить связь этого Cookies с конкретным пользователям.

                  Совсем необязательно, куки (а точнее авторизационный токен) уже может нести в себе всю информацию о сессии и пользователе.
                  • +1
                    >> Например — www.opennet.ru/base/sec/ssl_cert.txt.html

                    Сорри, про клиентские сертификаты забыл. Если после принятия сертификата сервер устанавливает пользователю сессию — это уже REST. Сам REST-сервис может работать по HTTPS, полагаясь на то, что сервер уже позаботился об авторизации клиента, но установление сессии выходит за рамки REST-сервиса.

                    >> Cookies нарушает принцип Stateless — серверу надо хранить связь этого Cookies с конкретным пользователям.

                    А чем тогда такой токен отличается от передачи в каждом запросе логина и пароля? И какой смысл тогда его хранить в куки?

                    Поясню свою точку зрения насчет передачи пароля в каждом запросе. Да, это способ сделать авторизацию в REST. Но любой другой способ, который сводится к этому, только лишь ненужное и бесполезное усложнение. В вашем случае с Cookie и токеном — фактически этот токен и является паролем, а сам пароль никому не нужен. То же самое с передачей зашифрованного пароля или хэша пароля.

                    REST работает поверх HTTP. В нем можно использовать любую HTTP аутентификацию (в том числе HTTPS). Но в рамках REST-сервиса аутентификацию производить можно только при каждом запросе заново.
                    • +3
                      Давайте определимся все-таки. Есть аутентификация — выдача пользователю некоего токена-пропуска, на основе его логина и пароля.
                      Авторизация — определение пользователя на основе токена и обеспечение доступа к некоторым запрошенным ресурсам.

                      Отличается это тем, что токен может нести в себе некоторые дополнительные данные, которые можно проверить и по которым можно определеить пользователя БЕЗ обращения к каким-либо базам данных.
                      Еще один плюс — у вам может быть несколько механизмов аутентификации (своя БД, аутентификация через всякие openauth, внешние сервисы и тому подобное), но единая авторизация за счет единого авторизационного токена. Ну или единый сервис аутентификации, который выдает токен и набор разных сервисов, которые этот токен принимают.
                      • +2
                        Все правильно, авторизацию должен проводить уже сам сервис (например, убедиться, что у текущего пользователя есть право запросить такую информацию). Но аутентификацию REST-сервис проводить не может, т.к. в этом случае он начинает хранить информацию о состоянии. Можно провести одновременно аутентификацию и авторизацию в рамках одного запроса (т.е. передаем логин и пароль в каждом запросе).

                        >> Отличается это тем, что токен может нести в себе некоторые дополнительные данные, которые можно проверить и по которым можно определить пользователя БЕЗ обращения к каким-либо базам данных.

                        А можно пример такой информации в токене? Что-то я придумать не могу.

                        Мое мнение:
                        1. Вся аутентификация на уровне HTTP/HTTPS и нижележащих протоколов (PPPoE какой-нибудь например) удовлетворяет REST идеологии (другой вопрос, как проводить авторизацию, т.е. передавать в сервис информацию о текущем пользователе, полученную уровнем ниже).
                        2. Аутентификация и авторизация в одном флаконе (логин/пароль в каждом запросе) также удовлетворяет REST.
                        3. Аутентификация и авторизация в разных запросах — не REST. Как минимум та часть, которая аутентификацией занимается уже не REST.

                        И немного в сторону. Есть сервис, который заводит пользователю сессию, записывает ее id в Cookie и при каждом пользовательском запросе проверяет в базе, есть ли там такая сессия. Это не REST, он хранит состояние. А другой сервис использует аутентификацию через сторонний сервис и при каждом пользовательском запросе уточняет у стороннего сервиса, валидный ли пользователь. Вроде бы REST, т.к. наш сервис состояний не хранит. И вот непонятно, по какому критерию собственная БД еще является хранением состояния, а сторонний сервис — уже нет. Фактически разработчик может сказать «У меня REST приложение. А БД — это внешний ресурс, это уже не REST». И никто ему в этом не помешает. Этот момент кажется мне очень спорным.
                        • 0
                          1. БД — это внешний ресурс, и состояние БД — это не есть состояние самого сервиса.
                          Сервисы с состоянием — это например сервисы в виде конечных автоматов (workflow services), которые ожидают вызовов от пользователя в строго определенном порядке и в зависимости от передаваемых данных

                          msdn.microsoft.com/en-us/magazine/cc164251.aspx

                          2. Есть целый стандартизованный формат для токенов (правда больше для soap) — en.wikipedia.org/wiki/Security_Assertion_Markup_Language

                          Соответственно, и примеры там есть ;)
                          • 0
                            1. А если сервис состояние хранит в файле в той же директории, что и сам находится, это тоже внешний ресурс? А если это перловый скрипт, который записывает информацию в массив в начале самого себя (знаю, что извращение, но все же), это ведь уже никак не внешний ресурс? Я это к тому, что по-моему не так важно где именно хранится состояние, а сам факт наличия этого состояния. И если при одинаковых входящих параметрах результат работы сервиса будет отличаться — это уже не REST.

                            2. Слишком много букв, сейчас нет времени читать внимательно. Бегло посмотрел, но примеров не увидел. Буду благодарен, если приведете такой пример на пальцах — интересно, как можно создать токен, который не хранится на сервере, не может быть подделан и чем-то принципиально отличается от передачи логина/пароля при каждом запросе.
                            • +1
                              1) Ну смотрите:
                              Я делаю GET somehost/someresource/100500
                              Далее кто-то делает POST somehost/someresource/100500 и изменяет ресурс который лежит по данному uri.
                              Когда я сделают такой же GET somehost/someresource/100500 я получу уже совсем другой результат. Это же не значит, что сервис уже не RESТ? А все потому что изменилось не состояние сервиса, а состояние некоего внешнего по отношению к сервису ресурса.
                              А поведение осталось то же — берем ресурс из БД, сериализуем и возвращаем пользователю.

                              А вот пример сервиса с воркфлоу: например у меня есть некий документооборот и я хочу создать некий ресурс-запись и привязать к нему некий набор файлов. С воркфлоу-сервисом возможен следующий вариант:
                              1. Я вызываю у сервиса некий метод «Создай мне ресурс», сервис его создает и запоминает состояние для моей сессии, что я только что просил у него создать ресурс и запоминает например некий внутренний идентификатор.
                              2. Несколькими последовательными запросами я заливаю файлы, причем сервис привязывает их к той записи, которую только что для меня создал.

                              Сценарий для типичной веб-разработки странный, но довольно-таки часто встречается в энтерпрайзном документообороте, что и породило разнообразные state machine движки.
                              Обратите внимание, что сервис по сути поменял интерфейс между шагом 1 и 2, как и положено конечному автомату.

                              2) Простой пример — токен может сразу нести в себе информацию о том, какими правами обладает пользователь или к какому множеству данных он может получить доступ, что позволяет их проверить без лишних запросов к той же БД. Так например работает Active Directory, что спасает в сильно распределенных системах.
                              • 0
                                1) Вот, же лучше. Т.е. REST-сервис — это сервис, поведение которого не меняется в зависимости от ранее выполненных запросов к этому же сервису.

                                В вашем примере с документооборотом — разносим создание документа и загрузку файлов по разным URL (первый вернет id нового документа, который будет использоваться при обращении к второму) и вуаля — REST приложение.

                                Из этого следует вывод: аутентификацию в REST можно делать как угодно, лишь бы для это был отдельный URL.

                                Небыстро мы до этого дошли.

                                2) Немного не в ту степь. Нужно проверить валидность токена без дополнительных запросов. То, что в токен можно положить разную информацию это само собой. Но я пока не увидел, каким образом как дополнительная информация в токене позволяет проверить его без дополнительных запросов.

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

                                Мне кажется решение этой задачи (если оно вообще есть) лежит в области криптографии и связано с каким-нибудь применением ассиметричного шифрования для подписи токена. Но я все еще сомневаюсь, что оно существует.
                                • 0
                                  > и который нельзя подделать
                                  токены обычно подписывают своим ключем
                                  • 0
                                    1. Все правильно, кроме того, что не все стейтлесс сервисы — обязательно REST.
                                    • 0
                                      Имелось в виду, stateless сервис, а не REST — это опечатка. Но и в таком виде покатит в качестве необходимого условия, не являющегося достаточным.
                                  • 0
                                    2. Именно подпись с открытым и закрытым ключами.
                                    • 0
                                      А от логина с паролем отличается только возможностью добавить в подписанное сообщение разную дополнительную информацию? Понятно.

                                      P.S. Ну что же вы сразу с этого не начали? С подписи с закрытым ключом и правильного определения stateless? Пришлось все это самому придумать, чтобы подтвердить вашу правоту.
                                      • +1
                                        Кроме дополнительной информации токен отличается тем, что не несет как правило «закрытой» информации (пароля того же), что повышает секьюрность.

                                        За многословность прошу прощения, не сразу понял в чем у вас недопонимание.
                                    • 0
                                      «Из этого следует вывод: аутентификацию в REST можно делать как угодно, лишь бы для это был отдельный URL.»

                                      А как же HTTP BAsic Authentication?
                                      • 0
                                        Про аутентификацию на уровне нижележащих протоколов речь уже не идет — по этому поводу ни у кого сомнений не возникает.
                                    • 0
                                      1) Ну смотрите:
                                      Я делаю GET somehost/someresource/100500
                                      Далее кто-то делает POST somehost/someresource/100500 и изменяет ресурс который лежит по данному uri.
                                      Когда я сделают такой же GET somehost/someresource/100500 я получу уже совсем другой результат. Это же не значит, что сервис уже не RESТ?

                                      откаменчу, что до этого мы предполагали, что сам ресурс, вокруг которых весь REST крутится, НЕ ИЗМЕНЯЕТСЯ пока мы там аутентифицируемся или еще что-то
                                      • 0
                                        > откаменчу, что до этого мы предполагали, что сам ресурс, вокруг которых весь REST
                                        > крутится, НЕ ИЗМЕНЯЕТСЯ пока мы там аутентифицируемся или еще что-то

                                        Т. е. блокируется что ли? А если у нас хайлоад какой-нибудь? Неее, не складывается что-то.
                                        • 0
                                          нет-нет, просто для упрощения рассуждений мы предполагали что ресурс не изменяется. А потом вроде как ввели новую переменную в рассуждения. Но суть от этого не меняется совершенно.
                                          • +1
                                            Просто надо понимать, что есть:
                                            1. Входные данные
                                            2. Некие бизнес-данные
                                            3. Некие данные о состоянии самого сервиса.

                                            И пока данных о состоянии сервиса нет и они не влияют на его поведение — сервис остается stateless.

                                            Грубо говоря:
                                            Если сервис возвращает, например, список пользователей, но после 100-го запроса внезапно переключает некий флаг и начинает возвращать список пользователей с каким-нибудь фильтром или вообще какой-нибудь другой список — то это stateful service.
                                            Если же он всегда возвращает список пользователей, но при этом кол-во пользователей в системе меняется и результат запроса естественно тоже меняется, то это не мешает сервису быть stateless.
                                            • 0
                                              все верно.

                                              давайте считать тот мой камент отсутвующим, он оказался запутывающим, а не уточняющим.
                                  • 0
                                    И если при одинаковых входящих параметрах результат работы сервиса будет отличаться — это уже не REST.

                                    В теории очень правильно.
                                    Жаль, мне не хватает практического опыта создания REST сервисов, но по-моему, это и на практике должно быть правдой.

                                    Логин-пароль или токен при этом не считаем входными данными.
                                    • 0
                                      > И если при одинаковых входящих параметрах результат работы сервиса будет отличаться — это уже не REST.
                                      > В теории очень правильно.

                                      Т.е. любой сервис, который возвращает мне результат некоего запроса к БД, которая может изменяться — это уже stateful-сервис?

                                      > Логин-пароль или токен при этом не считаем входными данными.

                                      А чем мы их считаем?
                                      • 0
                                        пропуском, можно сказать.

                                        Вывод функции от них не может изменяться, он может только отсутствовать, если прав нет.
                                        • +1
                                          Ок.
                                          Пример из коммента выше со списком пользователей системы:
                                          Юзер Вася директор филиала и может видеть только пользователей своего филиала.
                                          Юзер Дима админ всея системы и всегда видит всех пользователей системы.

                                          В итоге, сервис один, он все равно stateless, но вывод функции зависит от того какой пользователь делает запрос.
                                          • 0
                                            «Ок.
                                            Пример из коммента выше со списком пользователей системы:
                                            Юзер Вася директор филиала и может видеть только пользователей своего филиала.
                                            Юзер Дима админ всея системы и всегда видит всех пользователей системы.

                                            В итоге, сервис один, он все равно stateless, но вывод функции зависит от того какой пользователь делает запрос. „

                                            такое поведение функции мне кажется REST-неправильным и вот почему:

                                            директор Вася и Админ Дима должны использовать разные функции, а именно директор ex.com/users?department=34, админ — ex.com/users.
                                            Соответственно прав директора не хватит на вторую функцию, он в ответ на ее вызов ничего не получит.
                                            • 0
                                              Вопрос на самом деле очень интересный. Прошу небольшой перерыв для того чтобы порыться в книжках ;)
                                              • +1
                                                После обсуждения с коллегами и вкуривания в «SOA Designs Patterns» Томаса Эрла пришли к такому выводу:
                                                То что авторизационный токен передается отдельно от других входящих параметров, не означает, что токен не входит в множество входящих параметров. Бизнес-логика сервиса естественно может зависеть от параметров, в том числе и от параметра «залогинившийся пользователь».
                                                Соответственно, мой вариант сервиса вполне имеет право на существование, а ваш — все-таки решает немножко другую задачу (у вас два запроса — один на получение всех пользователей, второй — на получение пользователей конкретного отдела).
                                                • 0
                                                  Мне кажется, что «Бизнес-логика сервиса естественно может зависеть от параметров, в том числе и от параметра «залогинившийся пользователь».» — это нарушение принципа stateless…
                                                  • +1
                                                    Это означает, что вы неправильно понимаете, что означает stateless.
                                                    Смотрите, пусть есть некий черный ящик со входами и выходами, причем входами являются: входные данные, которые передает пользователь и некие бизнес-данные из внешних по отношению к сервису источников (база данных). Выходными данными является результат некоей обработки входов.
                                                    Тогда:
                                                    stateless-сервис будет всегда выводить на выход одни и то же значения при одних и тех же значения на входах
                                                    statefull-сервис имеет некую внутреннюю память (состояние) и выход зависит не только от текущих значений входа, но и от того что было на входах ранее.

                                                    Почитайте про конечные автоматы, понятнее будет ;)
                                                    • 0
                                                      да, теперь соглашусь, разъяснение помогло.

                                                      Меня смущало то, что я не понимал, как кешировать вывод в примере с одной функцией для админа и директора, теперь додумался, можно же добавить что-то varyByParam и кешировать отдельно для юзеров с разным набором прав.

                                                      Спасибо вам и вашим коллегам ;)
                                                      • 0
                                                        Не за что, рады помочь.
                                                    • +1
                                                      Сама логика внутри сервиса может быть сколь угодно сложной, главное чтобы она не учитывала «историю жизни сервиса».
                                    • 0
                                      3 пункта — отличное обобщение!

                                      По поводу сторонней БД, надо подумать, а не сломает ли нам эта штука кеширование…
                                      • 0
                                        Предыдущее было на
                                        «1. Вся аутентификация на уровне HTTP/HTTPS и нижележащих протоколов (PPPoE какой-нибудь например) удовлетворяет REST идеологии (другой вопрос, как проводить авторизацию, т.е. передавать в сервис информацию о текущем пользователе, полученную уровнем ниже).
                                        2. Аутентификация и авторизация в одном флаконе (логин/пароль в каждом запросе) также удовлетворяет REST.
                                        3. Аутентификация и авторизация в разных запросах — не REST. Как минимум та часть, которая аутентификацией занимается уже не REST.!»

                                        и «И немного в сторону. Есть сервис, который заводит пользователю сессию, записывает ее id в Cookie и при каждом пользовательском запросе проверяет в базе, есть ли там такая сессия. Это не REST, он хранит состояние. А другой сервис использует аутентификацию через сторонний сервис и при каждом пользовательском запросе уточняет у стороннего сервиса, валидный ли пользователь. Вроде бы REST, т.к. наш сервис состояний не хранит. И вот непонятно, по какому критерию собственная БД еще является хранением состояния, а сторонний сервис — уже нет. Фактически разработчик может сказать «У меня REST приложение. А БД — это внешний ресурс, это уже не REST». И никто ему в этом не помешает. Этот момент кажется мне очень спорным.»
                              • 0
                                имеется ввиду, что каждому клиенту генерится личный сертификат
                                пользователи с отозванным сертификата или без него не могут работать с сервом, и получают ошибку доступ запрещен
                                • 0
                                  Видимо statless не нужно понимать буквально. Достаточно лишь того, что бы состояние не хранилось в памяти конкретного сервера. Если сессии хранить в централизованной БД, то это вполне себе stateless.
                                  • +1
                                    Вы хотите сказать что все REST сервисы в интернете с кукисами — не REST сервисы?
                                    • 0
                                      Вот сюда загляните, там в пункте 1 вывод и определение stateless для REST сервисов. С которого товарищу retran надо было начинать и не было бы никаких вопросов. В статье же указано вот такое:

                                      >> Все операции клиента с сервером stateless, т.е. сервер не должен хранить вообще никакой информации о клиенте – никакой сессии

                                      Исходя из этого определения все, о чем я говорил, верно, хотя и не относится к REST.

                                      >> Вы хотите сказать что все REST сервисы в интернете с кукисами — не REST сервисы?

                                      Вы все-таки слишком обобщаете. О том, что нельзя использовать Cookie в REST архитектуре я ничего не говорил. Только о том, что их нельзя использовать для авторизации.
                                      • 0
                                        ок, поправлюсь:
                                        все REST сервисы в интернете с авторизацией с использованием кукисов/заголовков — не REST сервисы?
                                        • 0
                                          На этот вопрос я ответил в первой части своего комментария. Вы ведь его читали?
                                        • 0
                                          «О том, что нельзя использовать Cookie в REST архитектуре я ничего не говорил. Только о том, что их нельзя использовать для авторизации. „

                                          Почему? А если сценарий как описан тут?
                                        • 0
                                          нет
                                          • 0
                                            нет было ответом на «Вы хотите сказать что все REST сервисы в интернете с кукисами — не REST сервисы? „
                                    • +4
                                      Да хоть Basic :)
                                      Авторизация — часть запроса, ничего за его пределами не хранится.
                                      • 0
                                        В каждом сообщении передают юзера и пароль.
                                        • +6
                                          А очень просто. Сначала выполняем аутентификацию. При успешном входе, клиенту возвращаеться специально сгенерированный токен по которому могут идентифицировать клиента на сервере. Далее при каждом запросе к REST сервису, добавляется дополнительный заголовок «Authorization» в котором вы указываете тип авторизации и полученый токен.

                                          GET www.google.com/cse/api/default/cse/
                                          Authorization: GoogleLogin auth=IM6F7Cx2fo0TAiwlhNVdSE8Ov8hw6aHV
                                          • +1
                                            А токен этот генерируется и в БД записывается? Тогда у меня серьезные сомнения, что это укладывается в REST, т.к. отсутствует stateless.

                                            Если же аутентификация происходит не в рамках REST приложения, а в балансировщике/прокси, который перед ним работает — то все ок. Этот самый балансировщик уже не REST и он просто не пропускает запросы без заголовка Authorization. А в REST сервис балансировщик передает user_id, соответствующий токену.

                                            Именно поэтому токен передается в заголовке, а не в GET параметрах. GET параметры — это входящие данные для сервиса. А если сервис обрабатывает некий сгенерированный токен, значит он хранит информацию о состоянии. Если же он проверяет его только на соответствие какому-либо правилу (например, каждая вторая цифра четная) — это уже не авторизация. Ну и вообще, временные токены в GET передавать нельзя — они от этого портятся это мешает, например, кэшированию результатов работы сервиса.
                                            • 0
                                              Почему отсутствует stateless?

                                              Клиент делает запрос, к примеру:
                                              POST service.com/token/ передаешь ему логин пароль, сервис производит аутентификацию и в ответ отдает тебе токен. Токен хранится в базе и имеет разрешение/запреты на определенные действия.

                                              Дальше клиент делает те запросы которые ему нужны и в заголовке передает токен:
                                              GET service.com/car/1
                                              PUT service.com/car/1 и т.д.

                                              В итоге получается, что сервис не хранит твое состояние, ты создал новый ресурс, а потом просто запрашиваешь или изменяешь другие.

                                              Или я что-то путаю?)
                                              • +1
                                                Почитайте, пожалуйста, тут и тут. Все уже выяснено. Автор дал совершенно неправильное определение stateless, которым ввел меня (и не только) в заблуждение. Странно, что я повелся, т.к. у меня магистерский диплом был по REST-приложениям и включал реализацию одного из них. Забыл уже похоже, поверил и из него исходил. И других вводил в заблуждение. Каюсь.
                                                • 0
                                                  Т.е. получается, что мой вариант имеет место быть в REST архитектуре?
                                                  • 0
                                                    Да, все правильно. Пользуйтесь на здоровье)
                                          • 0
                                            Добавлю, что вариант с куки все-таки удобнее, если клиент работает из браузера. ИМХО, конечно.
                                            • +1
                                              Вообще-то это ничем не отличается от использования кук :)
                                              • 0
                                                Authorization — стандартизированный заголовок HTTP, он ближе к голому HTTP и соответственно больше соответствует идеологии REST.
                                                • +3
                                                  Куки — это просто хедер, он не ближе и не дальше. Так же как и хедер авторизации. Можно еще query param добавлять, видел и такое решение. Это все го лишь детали реализации. Важно, что сессия у вас есть в любой из реализаций и это не делает какую-либо реализацию ближе или дальше от HTTP.
                                                  • +2
                                                    Вопрос не в реализации, а в семантике. Если есть стандартизованный хидер, предназначенный специально для авторизационных токенов, то токены там и должны лежать в большинстве случаев.

                                                    То есть — если я увижу незнакомый сервис, то я буду с большей вероятностью ждать, что токен лежит именно в хидере авторизации, потому что это ближе к стандарту, соответственно поддержка сервиса для меня будет чуточку дешевле.
                                                    • +1
                                                      >Вопрос не в реализации, а в семантике. Если есть стандартизованный хидер, предназначенный специально для авторизационных токенов, то токены там и должны лежать в большинстве случаев.

                                                      Дык нет разницы в семантике. А сематника такова: передать (все равно как) токен, по этому токену идентифицировать сессию на сервере и выполнить запрос в контексте этой сессии. Но как раз вижу разницу в реализации.

                                                      >потому что это ближе к стандарту,

                                                      HTTP State Managend aka Cookie тоже очень и очень распространенный стандарт. Оба решения одинаковы, как по семантике, так и по стоимости поддержки.
                                                      • +2
                                                        Не согласен по поводу семантики.

                                                        Хидер Authorization введен специально для авторизации (RFC 2617).
                                                        Cookie — это механизм хранения информации о состоянии сессии (RFC 6265).

                                                        Лично мне разница очевидна.
                                                        • +1
                                                          Передача и обработка авторизационного токена через Authorization хедер есть частный случай реализации сессионного механизма. Куки — более общее решение.
                                                        • 0
                                                          На всякий случай — ru.wikipedia.org/wiki/%D0%A1%D0%B5%D0%BC%D0%B0%D0%BD%D1%82%D0%B8%D0%BA%D0%B0

                                                          То что вы называете семантикой — это не семантика (смысловое значение, грубо говоря), а описание процесса.
                                                • 0
                                                  Грамотный подход! Очень удобно в различных средах пользовать!
                                                • +1
                                                  А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?



                                                  <hr />
                                                  Цитата из педивикии:
                                                  Аутентифика́ция (англ. Authentication) — проверка принадлежности субъекту доступа предъявленного им идентификатора; подтверждение подлинности.[1]
                                                  Аутентификацию не следует путать с идентификацией и авторизацией[2].


                                                  Т.е. вопрос задан некорректно. Если не допускается хранения состояний то пароль/логин должны передаваться в каждом запросе, что логично. В этом и есть смысл stateless — всё необходимое для выполнения запроса (в том числе логин/пароль) передаётся каждый раз в каждом запросе.

                                                  REST предлагает не мудрить а использовать те средства которые есть в веб с начала времён. Для настройки прав доступа к каждому ресурсу можно использовать стандартные средства веб-сервера, для защиты трафика можно использовать стандартный HTTPS.

                                                  REST предлагает не плодить новые сущности а использовать то что уже давно прекрасно работает. Например для обозначения действия с ресурсом предлагается использовать указание типа запроса (POST, PUT, GET и т.п.) — но именно для этого типы запросов и были придуманы когда зарождался интернет.

                                                  • –1
                                                    другой пример — если ресурса нет то клиент полоучает стандартную 404 ошибку а не исключение или ещё что-то. Если нет доступа к ресурсу то, соответственно, ошибку 403.
                                                    • 0
                                                      >А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?

                                                      <hr />
                                                      Цитата из педивикии:
                                                      Аутентифика́ция (англ. Authentication) — проверка принадлежности субъекту доступа предъявленного им идентификатора; подтверждение подлинности.[1]
                                                      Аутентификацию не следует путать с идентификацией и авторизацией[2].

                                                      Т.е. вопрос задан некорректно

                                                      Он был задан для того, чтобы заставить читателей задуматься.
                                                    • 0
                                                      спасибо всем, кто помог ответить на вопрос.
                                                    • +6
                                                      Как настоящий зануда позволю себе заявить что автор статьи сравнивает протокол с парадигмой построения архитектуры веб серверов. Правильно было бы сравнивать RPC и REST, или SOAP и HTTP.
                                                      А по сути я так и не «почувствовал разницу», потому что в статье рассказывается в основном только про REST, а про SOAP пару упоминаний.

                                                      От себя могу сказать что RPC с одной стороны удобнее чем REST за счет того что он предоставляет WSDL, описывающий все возможности веб сервиса и позволяющий сгенерировать готовый код. RPC сервис обычно используют для реализации работы десктопных/консолных клиент серверных приложений.
                                                      С другой стороны REST сервис более прост в реализации и использовании именно для веб разработки.
                                                      • +4
                                                        позволю себе заявить что автор статьи сравнивает протокол с парадигмой построения архитектуры

                                                        Он как раз не сравнивает, а подчеркивает, что сравниваются разные вещи, что не правильно.
                                                        • 0
                                                          > позволю себе заявить что автор статьи сравнивает протокол с парадигмой построения архитектуры
                                                          Он как раз не сравнивает, а подчеркивает, что сравниваются разные вещи, что не правильно.

                                                          И первое и второе утверждение абсолютно верны.
                                                        • 0
                                                          >От себя могу сказать что RPC с одной стороны удобнее чем REST за счет того что он предоставляет WSDL,

                                                          Не-не, WSDL не является необходимым компонентом для RPC. Это как раз из протокола SOAP
                                                          • +3
                                                            SOAP — это не RPC. Точнее, есть SOAP 1.1 и SOAP 1.2. Первый — это ещё можно назвать RPC, а вот второй уже скорее с SMTP можно сравнивать, так как это протокол передачи сообщений, а не вызова удалённых процедур. Ну и если упоминать WSDL — то вообще RESTful и SOAP сравнивать нельзя.
                                                            SOAP и HTTP сравнивать вообще невозможно, это сравнение между эскалатором и пассажирами не нём.
                                                            Сделать WSDL для REST особых проблем не представляет, только стоит ли — получится SOAP.
                                                            • +1
                                                              >SOAP и HTTP сравнивать вообще невозможно, это сравнение между эскалатором и пассажирами не нём

                                                              Супер!
                                                          • +1
                                                            картинки не грузятся, перенесите пожалуйста например на habrastorage.org
                                                            • +1
                                                              > картинки не грузятся, перенесите пожалуйста например на habrastorage.org

                                                              у кого-нибудь еще есть такая проблема?

                                                              Камент от меня разработчикам Хабра: «Обязательно нужно добавить в HTML-редактор фунцкий вставки изображения c локального диска!»
                                                            • +1
                                                              "«REST vs SOAP» можно перефразировать в «Простота vs Стандарты»"
                                                              Я бы перефразировал на «Простота vs Избыточность», т.к. «Стандарты» — как мне кажется, применимы с какой-то долей к обоим с рамках соглашений.
                                                              • –6
                                                                Ох. Неужели этот выбор прям настолько важен, что определяет успех или неудачу продукта, и выбрав одно, изменить в будущем это будет очень сложно? Очевидно что нет. На успех/провал продукта это никак не влияет, а современный уровень развития технологий позволяет нам менять одно на другое без заметных усилий (естественно при условии, что мы помним про инкапсуляцию и SRP и стараемся их придерживаться). Тогда какая разница? Зачем писать об этом статьи
                                                                • –2
                                                                  Забавно) Кому-то этот выбор, похоже, кажется решающим, судя по минусам)
                                                                  • –1
                                                                    а при чем здесь успех или неудача? здесь технологии обсуждаются.
                                                                  • 0
                                                                    Не надо выбирать. Берете Axis2, пишете Java класс, объявляете его как сервис.
                                                                    После этого вы можете его вызывать как SOAP сервис и используя REST в т.ч. получая ответ в JSON представлении.

                                                                    Хотя SOAP это более полная функциональность, ведь еще есть

                                                                    — SAAJ/MTOM (пересылка эффективно бинарников, без кэширования в RAM)
                                                                    — XML-Signature (подписывание тела вызова сервиса)
                                                                    — XML Payload (возможность передать любой XML)
                                                                    • 0
                                                                      Напишите как-нибудь статью с примерами о том, как можно вызывать Axis2 сервис через REST? А то на официальном сайте Axis2 информации совсем мало по этому поводу. В частности, как передавать параметры — не совсем ясно.
                                                                    • +1
                                                                      1. Все через POST по HTTPS делать…
                                                                      2. В теле запроса передавать TokenId + все остальные поля
                                                                      3 .com/(get|post|update|delete)/car/(id)
                                                                      • +2
                                                                        Ну послушайте, опять статья про REST в которой нет ни одного упоминания гипертекста или HATEOAS (Кусок про «Link things together» засчитать за оные невозможно).

                                                                        Как раз для таких случаев Рой Филдинг и отрезал раз и навсегда: Если изменение состояния приложения не продиктовано гипертекстом — оно не может считаться RESTful.

                                                                        Это как бы и есть ключевое отличие REST (та самая суть, которую автор не уловил). Ссылки и их отношения вместо захардкоденых URI, медиа-типы и их описания вместо «описания форматов по заданным URI» — это про REST.

                                                                        Модель работы браузер — сервер и есть модель RESTful приложения. Клиент (браузер) знает только протокол взаимодействия (http), умеет интерпретировать медиа-тип (html).

                                                                        В умение интерпретировать медиа-тип включается и то, как интерпретировать встречающиеся в нем URI, как понимать их взаимоотношения. Например, один и тот же URL в тэгах «img», «a», «link» и «form method=post» интерпретируется по-разному, обеспечивая разные изменения состояния приложения.

                                                                        Но в этом и есть основная проблема при реализации REST API в данный момент. Общепризнанных гипермедиа-типов очень мало (text/html, application/atom+xml) и использовать их можно далеко не для каждой задачи. А описывать собственный… это уже совсем не просто.
                                                                        • 0
                                                                          Спасибо, очень ценное замечание. Я действительно рассматривал это в другом контексте
                                                                        • 0
                                                                          Добавлю еще общую штуку про аутентификацию для тех, у кого до сих пор не появилось четкого понимания, что она не нарушает принципы REST и что все в порядке =)

                                                                          1. В общем делаем мы запрос GET example.com/cars.
                                                                          2. Сервер смотрит — анонимный юзер, нельзя давать список машин
                                                                          3. Перенаправляет нас на сервер аутентификации
                                                                          4. мы там вводим имя-пароль
                                                                          5. Сервер проверяет данные и ставит нам куку
                                                                          6. Нас обратно перенаправляют на example.com/cars
                                                                          7. REST-сервис видит куку, проверяет ее и возвращает список машин. Самое важное, что это совершенно не является нарушением принципов REST. Мысля, как ASP.NET разработчик, эта проверка токена происходит в httpModule, т.е. то, что мы могли бы как-то назвать состоянием, не имеет ничего общего с собственно обработкой запроса — проверка происходит еще до попадания в функцию ответа на GET запрос.
                                                                          С кешированием тоже все ок — кешируется ведь результат работы той функции обработки GET запроса.

                                                                          • +1
                                                                            Как раз недавно пришлось работать с SOAP API
                                                                            Вот такой вот отличный WSDL отдает мне их сервер:
                                                                            habrastorage.org/storage1/4feea310/51c4201b/53a5c2f0/0f7c9c27.png :)
                                                                            • 0
                                                                              Задачи 2 и 3 прям так и шепчут «Реализуй нас, покупатели найдутся!».
                                                                              • 0
                                                                                «Для начала я бы назвал простоту основным преимуществом архитектуры REST». Может в этом смысл аббревиатуры? Расшифровка не слишком отражает идею, а вот сокращение REST — вполне. Just rest и не заморачивайся о статусах, just rest и используй стандартные методы HTTP

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