Как я уже писал раньше, REST обладает таким свойством как Statelessness или независимости от состояния. Проще говоря, REST не хранит на сервере какое-либо клиентское состояние или сессию. Каждый вызов к REST сервису по одному и тому же адресу URI, и с тем же HTTP Verb по сути обрабатывается одинаково.
С одной стороны – это преимущество. Потому что не нужно расходовать ресурсы сервера на то, чтобы хранить состояние. С другой стороны, такие типичные сценарии, как например авторизация пользователя, просто невозможно выполнить не сохраняя где-то состояние. Пожалуй, это пока единственный самый распространенный сценарий, который мне сейчас приходит в голову, и в котором необходимо хранить состояние.
Как следствие отсутствия состояния в REST – возможность более высокой нагрузки таких сервисов и хорошая масштабируемость. Так как запросы к сервису независимые, то и масштабировать становится проще.
Изображение 1 и 2 иллюстрирует сервисы, которые хранят сессию и нет соответственно. Например тут запрашивается следующая страница результатов:
Изображение 1

Такой же сервис только состояние не хранится на сервисе.
Изображение 2

В сервисах, которые оперируют сессией, данные связанные с ней хранит как сервер (по большей части), так и клиент, для того чтобы можно было правильно идентифицировать клиента и синхронизироваться с клиентом.
В REST эту обязанность на себя перенимает клиент. Использовать можно любой способ передачи параметров с клиента на сервер. Но чаще всего, используются HTTP Headers.
Рассмотрим пример того как REST обходится без сохранения сессии и состояния на сервере для сценария авторизации. При авторизации сервер выдает клиенту токен. Токен – это может быть какой-то идентификатор пользователя, плюс отметка времени когда он выдан, плюс подпись этого дела. Клиент помещает в каждый свой запрос такой токен в стандартный (Authorization) или кастомный HTTP Header. Каждый раз, когда клиент приходит на сервер – данные переподписываются и подписи сравниваются, сравниваются и даты, не истек ли срок на которые выдан токе. Дальше, извлекается идентификтор пользователя и теперь можно на сервере делать свои черные дела (выполнять бизнес логику например).
Вот пример такого запроса
GET https://myaddressbook.com/contacts/7 HEADERS: Accept: application/json Authorization: WRAP access_token="http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fsid=7&http%3a%2f%2fschemas.microsoft.com%2fws%2f2008%2f06%2fidentity%2fclaims%2frole=http%3a%2f%2fschemas.myaddressvook.com%2fmyLibreeze%2fpermission%2fmodify&Issuer=OAuthProvider&Audience=http%3a%2f%2fmyaddressvook%2frp&ExpiresOn=1337764852&HMACSHA256=fUcljUY7i9rpiNvFp%2bPszYBf2AkCDjHHC7wPcGV21NE%3d"в данном случае в заголовке передается страшный токен:
WRAP access_token="http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fsid=7&http%3a%2f%2fschemas.microsoft.com%2fws%2f2008%2f06%2fidentity%2fclaims%2frole=http%3a%2f%2fschemas.myaddressvook.com%2fmyaddressvook%2fpermission%2fmodify&Issuer=OAuthProvider&Audience=http%3a%2f%2fmylibreeze%2frp&ExpiresOn=1337764852&HMACSHA256=fUcljUY7i9rpiNvFp%2bPszYBf2AkCDjHHC7wPcGV21NE%3d"
В нем даже можно различить схему по которой он создан, где подпись, и маркер времени и даже идентификатор пользователя – 7, вся соль в плане безопасности в данном случае в подписи.
На токен может быть совсем другой – более короткий, и данные могут быть скрыты. Для того, как REST работает с состоянием – это не есть существенно. И все это счастье гоняется с каждым запросом на сервер. Если длина токена в данном случае смущает – ее можно сократить. Да, конечно же, есть небольшой overhead, но состояние все таки нужно как-то передать.
Например Amazon AWS для таких сценариев использует другой токен:
POST /2013-08-05/distribution HTTP/1.1 Host: cloudfront.amazonaws.com Date: Thu, 05 Aug 2013 17:08:48 GMT Authorization: AWS AKIAIOSFODNN7EXAMPLE:111111112222222jPXo7+e/YSu0g= [Other required headers]Еще один момент, в котором могут понадобится сессии – это обеспечение непротиворечивости данных и concurrency.
Представим себе ситуацию. Два пользователя выгребли у сервера данные, один из пользователей успел изменить данные, отправить их на сервер. Теперь у пользователя который ничего не меня старая версия данных и он может перезаписать новую версию.
На самом деле в большинстве случаев такие проблемы решаются на уровне базы. Но если так не получается то можно использовать для этого Etag вместе с If-None-Match header, например для того, чтобы контролировать concurrency.
Вот так в грубом виде на примере авторизации и работает REST с состояниями.
Итак, основная идея REST Statelessness в том, что состояние хранится не на сервере, а на клиенте. Клиент же получает от сервера все необходимые данные, чтобы это состояние на сервер передавать.
Комментариев нет:
Отправить комментарий