Rest принципы что это
REST: простым языком
Feb 8, 2019 · 6 min read
(REpresentational State Transfer) — это архитектура, т.е. принципы построения распределенных гипермедиа систем, того что другими словами называется World Wide Web, включая универсальные способы обработки и передачи состояний ресурсов по HTTP
Автор идеи и термина Рой Филдинг 2000г.
REST на сегодняшний день практически вытеснил все остальные подходы, в том числе дизайн основанный на SOAP и WSDL
Что нам дает REST подход
Когда использовать REST?
• Когда есть ограничение пропускной способности соединения
• Если необходимо кэшировать запросы
• Если система предполагает значительное масштабирование
• В сервисах, использующих AJAX
Преимущества REST:
Что такое RESTful:
Чтобы распреде л енная система считалась сконструированной по REST архитектуре (Restful), необходимо, чтобы она удовлетворяла следующим критериям:
Четыре принципа единого интерфейса:
6. Code-On-Demand (опционально). В REST позволяется загрузка и выполнение кода или программы на стороне клиента.
Серверы могут временно расширять или кастомизировать функционал клиента, передавая ему логику, которую он может исполнять. Например, это могут быть скомпилированные Java-апплеты или клиентские скрипты на Javascript
Идемпотентность
С точки зрения RESTful-сервиса, операция (или вызов сервиса) идемпотентна тогда, когда клиенты могут делать один и тот же вызов неоднократно при одном и том же результате на сервере. Другими словами, создание большого количества идентичных запросов имеет такой же эффект, как и один запрос. Заметьте, что в то время, как идемпотентные операции производят один и тот же результат на сервере, ответ сам по себе может не быть тем же самым (например, состояние ресурса может измениться между запросами).
Методы PUT и DELETE по определению идемпотентны. Тем не менее, есть один нюанс с методом DELETE. Проблема в том, что успешный DELETE-запрос возвращает статус 200 (OK) или 204 (No Content), но для последующих запросов будет все время возвращать 404 (Not Found), Состояние на сервере после каждого вызова DELETE то же самое, но ответы разные.
Методы GET, HEAD, OPTIONS и TRACE определены как безопасные. Это означает, что они предназначены только для получения информации и не должны изменять состояние сервера. Они не должны иметь побочных эффектов, за исключением безобидных эффектов, таких как: логирование, кеширование, показ баннерной рекламы или увеличение веб-счетчика.
По определению, безопасные операции идемпотентны, так как они приводят к одному и тому же результату на сервере. Безопасные методы реализованы как операции только для чтения. Однако безопасность не означает, что сервер должен возвращать тот же самый результат каждый раз.
HTTP методы для создания RESTful сервисов
HTTP метод GET используется для получения (или чтения) представления ресурса. В случае “удачного” (или не содержащего ошибок) адреса, GET возвращается представление ресурса в формате XML или JSON в сочетании с кодом состояния HTTP 200 (OK). В случае наличия ошибок обычно возвращается код 404 (NOT FOUND) или 400 (BAD REQUEST).
HTTP метод PUT обычно используется для предоставления возможности обновления ресурса. Тело запроса при отправке PUT-запроса к существующему ресурсу URI должно содержать обновленные данные оригинального ресурса (полностью, или только обновляемую часть).
Для создания новых экземпляров ресурса предпочтительнее использование POST запроса. В данном случае, при создании экземпляра будет предоставлен корректный идентификатор экземпляра ресурса в возвращенных данных об экземпляре.
При успешном обновлении посредством выполнения PUT запроса возвращается код 200 (или 204 если не был передан какой либо контент в теле ответа). PUT не безопасная операция, так как вследствии ее выполнения происходит модификация (или создание) экземпляров ресурса на стороне сервера, но этот метод идемпотентен. Другими словами, создание или обновление ресурса посредством отправки PUT запроса — ресурс не исчезнет, будет располагаться там же, где и был при первом обращении, а также, многократное выполнение одного и того же PUT запроса не изменит общего состояния системы
HTTP метод POST запрос наиболее часто используется для создания новых ресурсов. На практике он используется для создания вложенных ресурсов. Другими словами, при создании нового ресурса, POST запрос отправляется к родительскому ресурсу и, таким образом, сервис берет на себя ответственность на установление связи создаваемого ресурса с родительским ресурсом, назначение новому ресурсу ID и т.п.
При успешном создании ресурса возвращается HTTP код 201, а также в заголовке `Location` передается адрес созданного ресурса.
POST не является безопасным или идемпотентным запросом. Потому рекомендуется его использование для не идемпотентных запросов. В результате выполнения идентичных POST запросов предоставляются сильно похожие, но не идентичные данные.
HTTP метод DELETE используется для удаления ресурса, идентифицированного конкретным URI (ID).
При успешном удалении возвращается 200 (OK) код HTTP, совместно с телом ответа, содержащим данные удаленного ресурса. Также возможно использование HTTP кода 204 (NO CONTENT) без тела ответа. Согласно спецификации HTTP, DELETE запрос идемпотентен. Если вы выполняете DELETE запрос к ресурсу, он удаляется. Повторный DELETE запрос к ресурсу закончится также: ресурс удален. Если DELETE запрос используется для декремента счетчика, DELETE запрос не является идемпотентным. Используйте POST для не идемпотентных операций.
Тем не менее, существует предостережение об идемпотентности DELETE. Повторный DELETE запрос к ресурсу часто сопровождается 404 (NOT FOUND) кодом HTTP по причине того, что ресурс уже удален (например из базы данных) и более не доступен. Это делает DELETE операцию не идемпотентной, но это общепринятый компромисс на тот случай, если ресурс был удален из базы данных, а не помечен, как удаленный.
Архитектура REST
Введение
В русскоязычной части Интернета присутствует большое количество статей, посвященных веб-службам на основе SOAP и XML-RPC, но почему-то почти ничего нет про вполне заслуживающую внимания (но менее распространенную) архитектуру RESТ.
В данной статье описываются основы этой архитектуры, возможности и примеры её использования.
Что такое REST
REST (Representational state transfer) – это стиль архитектуры программного обеспечения для распределенных систем, таких как World Wide Web, который, как правило, используется для построения веб-служб. Термин REST был введен в 2000 году Роем Филдингом, одним из авторов HTTP-протокола. Системы, поддерживающие REST, называются RESTful-системами.
В общем случае REST является очень простым интерфейсом управления информацией без использования каких-то дополнительных внутренних прослоек. Каждая единица информации однозначно определяется глобальным идентификатором, таким как URL. Каждая URL в свою очередь имеет строго заданный формат.
А теперь тоже самое более наглядно:
Отсутствие дополнительных внутренних прослоек означает передачу данных в том же виде, что и сами данные. Т.е. мы не заворачиваем данные в XML, как это делает SOAP и XML-RPC, не используем AMF, как это делает Flash и т.д. Просто отдаем сами данные.
Каждая единица информации однозначно определяется URL – это значит, что URL по сути является первичным ключом для единицы данных. Т.е. например третья книга с книжной полки будет иметь вид /book/3, а 35 страница в этой книге — /book/3/page/35. Отсюда и получается строго заданный формат. Причем совершенно не имеет значения, в каком формате находятся данные по адресу /book/3/page/35 – это может быть и HTML, и отсканированная копия в виде jpeg-файла, и документ Microsoft Word.
Как происходит управление информацией сервиса – это целиком и полностью основывается на протоколе передачи данных. Наиболее распространенный протокол конечно же HTTP. Так вот, для HTTP действие над данными задается с помощью методов: GET (получить), PUT (добавить, заменить), POST (добавить, изменить, удалить), DELETE (удалить). Таким образом, действия CRUD (Create-Read-Updtae-Delete) могут выполняться как со всеми 4-мя методами, так и только с помощью GET и POST.
Вот как это будет выглядеть на примере:
GET /book/ — получить список всех книг
GET /book/3/ — получить книгу номер 3
PUT /book/ — добавить книгу (данные в теле запроса)
POST /book/3 – изменить книгу (данные в теле запроса)
DELETE /book/3 – удалить книгу
ВАЖНОЕ ДОПОЛНЕНИЕ: Существуют так называемые REST-Patterns, которые различаются связыванием HTTP-методов с тем, что они делают. В частности, разные паттерны по-разному рассматривают POST и PUT. Однако, PUT предназначен для создания, реплейса или апдейта, для POST это не определено (The POST operation is very generic and no specific meaning can be attached to it). Поэтому мой пример будет правильным и в таком виде, и в виде если поменять местами POST и PUT.
Вообще, POST может использоваться одновременно для всех действий изменения:
POST /book/ – добавить книгу (данные в теле запроса)
POST /book/3 – изменить книгу (данные в теле запроса)
POST /book/3 – удалить книгу (тело запроса пустое)
Это позволяет иногда обходить неприятные моменты, связанные с неприятием PUT и DELETE.
Использование REST для построения Web-сервисов.
Как известно, web-сервис – это приложение работающее в World Wide Web и доступ к которому предоставляется по HTTP-протоколу, а обмен информации идет с помощью формата XML. Следовательно, формат данных передаваемых в теле запроса будет всегда XML.
Для каждой единицы информации (info) определяется 5 действий. А именно:
GET /info/ (Index) – получает список всех объектов. Как правило, это упрощенный список, т.е. содержащий только поля идентификатора и названия объекта, без остальных данных.
GET /info/ (View) – получает полную информацию о объекте.
PUT /info/ или POST /info/ (Create) – создает новый объект. Данные передаются в теле запроса без применения кодирования, даже urlencode. В PHP тело запроса может быть получено таким способом:
POST /info/ или PUT /info/ (Edit) – изменяет данные с идентификатором
DELETE /info/ (Delete) – удаляет данные с идентификатором
Еще раз отмечу, что в нашем примере /info/ — может и базироваться на какой-то другой информации, что может быть (и должно) быть отражено в URL:
/data/4/otherdata/6/info/3/ … и тому подобное.
Какие можно сделать из этого выводы:
Как видно, в архитектура REST очень проста в плане использования. По виду пришедшего запроса сразу можно определить, что он делает, не разбираясь в форматах (в отличие от SOAP, XML-RPC). Данные передаются без применения дополнительных слоев, поэтому REST считается менее ресурсоемким, поскольку не надо парсить запрос чтоб понять что он должен сделать и не надо переводить данные из одного формата в другой.
Практическое применение.
Самое главное достоинство сервисов в том, что с ними работать может какая угодно система, будь то сайт, flash, программа и др. так как методы парсинга XML и выполнения запросов HTTP присутствуют почти везде.
Архитектура REST позволяет серьезно упростить эту задачу. Конечно в реальности, того что описано не достаточно, ведь нельзя кому угодно давать возможность изменять информацию, то есть нужна еще авторизация и аутентификация. Но это достаточно просто разрешается при помощи различного типа сессий или просто HTTP Authentication.
Введение в REST API — RESTful веб-сервисы
Эта статья начинает серию постов о разработке REST API:
Intro to RESTful Web Services
REST означает REpresentational State Transfer (Википедия: «передача состояния представления»). Это популярный архитектурный подход для создания API в современном мире.
Вы изучите:
Что такое REST?
REST расшифровывается как REpresentational State Transfer. Это был термин, первоначально введен Роем Филдингом (Roy Fielding), который также был одним из создателей протокола HTTP. Отличительной особенностью сервисов REST является то, что они позволяют наилучшим образом использовать протокол HTTP. Теперь давайте кратко рассмотрим HTTP.
Краткий обзор HTTP
Давайте сначала откроем браузер и зайдем на веб-страницу:
А затем щелкните на одной из страниц результатов:
Далее мы можем нажать на ссылку на странице, на которой мы оказались:
И перейти на другую страницу:
Вот как мы обычно просматриваем веб страницы.
Когда мы просматриваем страницы в Интернете, за кулисами происходит много вещей. Ниже приведено упрощенное представление о том, что происходит между браузером и серверами, работающими на посещаемых веб-сайтах:
Протокол HTTP
Когда вы вводите в браузере URL-адрес, например www.google.com, на сервер отправляется запрос на веб-сайт, идентифицированный URL-адресом.
Затем этот сервер формирует и выдает ответ. Важным является формат этих запросов и ответов. Эти форматы определяются протоколом HTTP — Hyper Text Transfer Protocol.
Когда вы набираете URL в браузере, он отправляет запрос GET на указанный сервер. Затем сервер отвечает HTTP-ответом, который содержит данные в формате HTML — Hyper Text Markup Language. Затем браузер получает этот HTML-код и отображает его на экране.
Допустим, вы заполняете форму, присутствующую на веб-странице, со списком элементов. В таком случае, когда вы нажимаете кнопку «Submit» (Отправить), HTTP-запрос POST отправляется на сервер.
HTTP и RESTful веб-сервисы
HTTP обеспечивает базовый уровень для создания веб-сервисов. Поэтому важно понимать HTTP. Вот несколько ключевых абстракций.
Ресурс
Ресурс — это ключевая абстракция, на которой концентрируется протокол HTTP. Ресурс — это все, что вы хотите показать внешнему миру через ваше приложение. Например, если мы пишем приложение для управления задачами, экземпляры ресурсов будут следующие:
URI ресурса
Когда вы разрабатываете RESTful сервисы, вы должны сосредоточить свое внимание на ресурсах приложения. Способ, которым мы идентифицируем ресурс для предоставления, состоит в том, чтобы назначить ему URI — универсальный идентификатор ресурса. Например:
REST и Ресурсы
Важно отметить, что с REST вам нужно думать о приложении с точки зрения ресурсов:
Определите, какие ресурсы вы хотите открыть для внешнего мира
Используйте глаголы, уже определенные протоколом HTTP, для выполнения операций с этими ресурсами.
Вот как обычно реализуется служба REST:
Компоненты HTTP
HTTP определяет следующую структуру запроса:
Методы HTTP-запроса
Метод, используемый в HTTP-запросе, указывает, какое действие вы хотите выполнить с этим запросом. Важные примеры:
Код статуса ответа HTTP
Код состояния всегда присутствует в ответе HTTP. Типичные примеры:
Резюме
В статье приведен на верхнем уровне обзор архитектурного стиля REST. Подчеркивается тот факт, что HTTP является основным строительным блоком REST сервисов. HTTP — это протокол, который используется для определения структуры запросов и ответов браузера. Мы видели, что HTTP имеет дело главным образом с ресурсами, доступными на веб-серверах. Ресурсы идентифицируются с помощью URI, а операции над этими ресурсами выполняются с использованием глаголов, определенных протоколом HTTP.
Наконец, мы рассмотрели, как службы REST наилучшим образом используют функции, предлагаемые HTTP, для предоставления ресурсов внешнему миру. REST не накладывает никаких ограничений на форматы представления ресурсов или на определение сервиса.
Основы REST: теория и практика
Авторизуйтесь
Основы REST: теория и практика
REST, Representational State Transfer, является архитектурным стилем для обеспечения стандартов между компьютерными системами в сети, что облегчает для систем обмен данными друг с другом. Системы, отвечающие требованиям REST и часто называемые RESTful, характеризуются тем, что не имеют сохранения состояния и разделяют интересы клиента и сервера. Мы рассмотрим, что означают эти термины и почему они являются полезными для услуг в Интернете.
Разделение клиента и сервера
В архитектурном стиле REST реализация клиента и реализация сервера могут быть выполнены независимо друг от друга. Это означает, что код на стороне клиента может быть изменён в любое время без ущерба для работы сервера, а код на стороне сервера может быть изменён без влияния на работу клиента.
До тех пор, пока каждая сторона знает, какой формат сообщений следует направлять другой стороне, они могут храниться модульно и раздельно. Отделяя задачи пользовательского интерфейса от задач хранения данных, мы повышаем гибкость интерфейса между платформами и улучшаем расширяемость за счёт упрощения компонентов сервера. Кроме того, разделение позволяет каждому компоненту развиваться независимо.
Используя интерфейс REST, различные клиенты попадают в одни и те же конечные точки REST, выполняют те же действия и получают одинаковые ответы.
Отсутствие сохранения состояния
Системы, которые следуют парадигме REST, не имеют сохранения состояния, что означает, что серверу не нужно знать о состоянии клиента и наоборот. Таким образом, и сервер, и клиент могут понять любое полученное сообщение, даже не увидев предыдущих сообщений. Это отсутствие сохранения состояния обеспечивается за счёт использования ресурсов, а не команд. Они описывают любые объекты, документы или вещи, которые могут потребоваться для хранения или отправки в другие службы.
Эти ограничения помогают RESTful-приложениям достигать надёжности, быстрой производительности и расширяемости, как компонентам, которые могут быть управляемы, обновлены и повторно использованы, не затрагивая систему в целом даже во время её работы.
Теперь мы изучим, как на самом деле происходит взаимодействие между клиентом и сервером, когда мы внедряем RESTful-интерфейс.
Взаимодействие между клиентом и сервером
В архитектуре REST клиенты отправляют запросы на поиск или изменение ресурсов, а серверы отправляют ответы на эти запросы. Давайте рассмотрим стандартные способы направления запросов и ответов.
Отправка запросов
REST требует, чтобы клиент сделал запрос на сервер для получения или изменения данных на сервере. Запрос обычно состоит из:
Существует 4 основных метода НТТР, которые мы используем в запросах для взаимодействия с ресурсами в системе REST:
В заголовке запроса клиент отправляет тип контента, который он может получить с сервера. Это поле называется Accept. Оно обеспечивает, что сервер не посылает данные, которые не могут быть поняты или обработаны клиентом. Параметры типов контента — это типы MIME (или Multipurpose Internet Mail Extensions, о которых вы можете прочитать больше в MDN Web Docs).
Типы MIME, используемые для указания типов контента в поле Accept, состоят из типа и подтипа. Они разделены слэшем (/).
Другие типы и часто используемые подтипы:
Например, клиент, имеющий доступ к ресурсу с идентификатором 123 в ресурсе статей на сервере, может отправить запрос GET следующим образом:
Запросы должны содержать путь к ресурсу, на котором должна выполняться операция. В RESTful API пути должны быть разработаны так, чтобы помочь клиенту понять, что происходит. Обычно первая часть пути должна быть множественной формой ресурса. Это позволяет легко читать и понимать вложенные пути.
Пути должны содержать информацию, необходимую для определения местоположения ресурса с необходимой степенью конкретности. При ссылке на список или коллекцию ресурсов не всегда необходимо добавлять идентификатор. Например, запрос POST на путь somesite.com/persons не будет нуждаться в дополнительном идентификаторе, так как сервер генерирует идентификатор для нового объекта.
В тех случаях, когда сервер отправляет клиенту полезную нагрузку, он должен включать тип контента в заголовок ответа. Это поле заголовка контента предупреждает клиента о типе данных, которые он посылает в теле ответа. Эти типы контента являются типами MIME, точно так же, как они находятся в поле Accept заголовка запроса. Тип контента, который сервер возвращает обратно в ответе, должен быть одним из параметров, указанных клиентом в поле принятия запроса.
Например, клиент получает доступ к ресурсу с идентификатором 123 в разделе статей с этим запросом GET:
Сервер должен отправить обратно контент с заголовком ответа:
Это означает, что запрашиваемый контент возвращается в тело ответа с text/html — типом контента, который клиент будет в состоянии принять.
Коды ответов
Ответы от сервера содержат коды состояния для оповещения клиента об успехе операции. Как разработчику вам не нужно знать каждый код состояния (их много), но вы должны знать самые распространённые и то, как они используются.
Для каждого метода НТТР ожидаются коды статуса, которые сервер должен вернуть в случае успеха:
Если операция не работает, вернётся наиболее конкретный код состояния, соответствующий возникшей проблеме.
Предположим, у нас есть приложение, которое позволяет вам просматривать, создавать, редактировать и удалять клиентов и заказы для небольшого магазина одежды, размещённого на сайте fashionboutique.com. Мы можем создать НТТР API, который позволит клиенту выполнять следующие функции.
Если бы мы хотели увидеть всех клиентов, запрос выглядел бы так:
Возможный заголовок ответа будет выглядеть следующим образом:
Создание нового клиента путем размещения данных:
Затем сервер генерирует идентификатор этого объекта и возвращает его клиенту с таким заголовком:
Для просмотра одного клиента мы используем метод GET, указывая идентификатор этого клиента:
Возможный заголовок ответа будет выглядеть следующим образом:
Мы можем обновить этого клиента, вставив новые данные с помощью метода PUT:
Мы также можем УДАЛИТЬ этого клиента, указав его идентификатор:
Практика с REST
Давайте представим, что мы создаём сайт для сбора фотографий. Мы хотим сделать API, чтобы отслеживать пользователей, места проведения и фотографии этих мест. Этот сайт имеет index.html и style.css. Каждый пользователь имеет имя пользователя и пароль. Каждая фотография имеет место проведения и владельца (т.е. пользователя, который сделал фотографию). Каждое место имеет название и адрес. Можете ли вы разработать систему REST, которая будет учитывать:
Для начала опишите:
REST, что же ты такое? Понятное введение в технологию для ИТ-аналитиков
Мы подготовили статью Андрея Буракова на основе его вебинара на нашем YouTube-канале:
Проектирование и работа с REST-сервисами стали повседневными задачами для многих аналитиков. Однако мы часто встречаемся на работе с различными или даже противоречащими друг другу трактовками таких понятий, как REST, RESTful-сервис, RESTAPI.
Сегодня мы разберём, какие принципы вложил в парадигму REST её автор и как они могут помочь нам при проектировании систем.
Выясним, почему существует терминологическая путаница вокруг REST и как нам научиться лучше понимать коллег.
Поговорим о том, как связаны HTTP и REST. А также почему REST противопоставляют SOAP.
Терминология
Формат представления данных
Давайте представим, что я живу в девятнадцатом веке и хочу отправить письмо своему клиенту, который заинтересован в покраске своего автомобиля. Разумеется, я должен написать в письме про то, какие цвета для покраски автомобиля имеются в автосалоне.
Перед тем, как отправить письмо, я беру лист бумаги и пишу клиенту, что в автосалоне сейчас доступны цвета: синий, зелёный, красный, белый, чёрный.
Но я мог бы написать это и на английском: blue, green, red, white, black.
Выходит, что одна и та же информация может быть представлена разными способами. И такой способ представления одной и той же информации разными способами будем называть форматом представления данных.
Plain text — это обычный текст, который я использовал при написании письма;
XML — язык разметки информации;
JSON — текстовый формат обмена данными;
Binary — бинарный формат.
Давайте запомним из этой части статьи что XML и JSON — это форматы представления данных.
Протокол передачи данных
Я написал письмо и теперь хочу его отправить. Что мне нужно для этого сделать? Как правило, я кладу письмо в конверт. В нашем случае таким конвертом будет такое понятие, как протокол передачи данных.
Протокол передачи данных — это набор соглашений, которые определяют обмен данными между различными программами. Эти соглашения задают единообразный способ передачи сообщений и обработки ошибок.
Аналогия протокола передачи данных с письмом в конверте
Если продолжать рассматривать аналогию с письмом, то стоит обратить, что:
1. конверт имеет структуру;
2. я наклеиваю на конверт марки, указываю определённую информацию: от кого письмо, куда я его отправляю, адрес и т.д.
Транспорт
Получил письмо в конверте, всё здорово! Но нужно его как-то отправить. Как мне его отправить? Я воспользуюсь услугами почты. Что для этого нужно сделать? Прийти на почту, отдать письмо. Затем его кто-то должен доставить, используя некоторый транспорт.
Транспорт — это подмножество сетевых протоколов, с помощью которых мы можем передавать данные по сети.
Такими протоколами могут быть, например: HTTP, AMQP, FTP.
Если продолжать аналогию с письмом, то почтовая служба может отправить это письмо с помощью голубя или, например, с помощью совы. Вроде бы, письмо одно и то же. Конверт (протокол) один и тот же, формат данных один и тот же, но, обратите внимание — транспорт разный.
Протокол HTTP
HyperText Transfer Protocol (HTTP) — это протокол передачи данных. Изначально для передачи данных в виде гипертекстовых документов в формате HTML, сегодня — для передачи произвольных данных.
Этот протокол имеет две особенности, которые должны учитывать все, кто работает с этим протоколом: ресурсы и HTTP-глаголы.
Ресурсы
Чтобы разобраться с понятием ресурса, давайте представим, что у нас имеется некоторая ссылка: http://webinar.ru/schedule/speech.
Это как раз и есть тот самый URL, который мы используем поверх HTTP. Рассмотрим, из чего состоит эта ссылка:
А вот как нам работать с этими объектами, нам говорят HTTP-глаголы (методы).
HTTP-глаголы
HTTP-глаголы — это элемент протокола HTTP, который используется в каждом запросе, чтобы указать, какое действие нужно выполнить над данным ресурсом.
GET/schedule/speech/id413 — получить информацию об объекте
Здесь мы видим некоторый объект (ресурс) с конкретным идентификатором с номером 413. Я могу использовать HTTP-глагол GET для, того чтобы получить информацию о выступлении 413.
Я могу воспользоваться каким-либо другим HTTP-глаголом, если мне необходимо выполнить какие-либо другие действия.
PUT/schedule/speech/id413 — создать или перезаписать объект
Или удалить объект:
Главное здесь то, что мы рассматриваем некоторые объекты (ресурсы) и совершаем над ними некоторые действия, которые определены в протоколе списком HTTP-методов: GET, PUT, POST, DELETE и т.д.
Что такое REST?
Какое же определение в понятие REST заложил его основатель Рой Филдинг?
Representational State Transfer — это архитектурный стиль взаимодействия компонентов распределённого приложения в сети. Архитектурный стиль – это набор согласованных ограничений и принципов проектирования, позволяющий добиться определённых свойств системы.
Но зачем нам REST? Зачем нам этот стиль? Что нам даст применение принципов REST?
Если мы обратимся опять же к первоисточнику — к работе Филдинга, то мы выясним, что назначение REST в том, чтобы придать проектируемой системе такие свойства как:
Гибкость к изменениям,
Это наиболее ценные свойства, с которыми встречается, например, аналитик при проектировании систем. В действительности их намного больше. Если внимательно посмотреть на эти свойства, то мы увидим ни что иное, как нефункциональные требования к системе, которых мы на своих проектах стремимся достичь.
Принципы REST
Каким образом REST может помочь нам достичь этих свойств и реализовать эти нефункциональные требования?
Чтобы это понять, давайте рассмотри 6 принципов REST — ограничений, которые и помогают нам добиться этих нефункциональных требований.
6 принципов REST:
Далее мы рассмотрим эти шесть принципов поподробнее.
Принцип 1. Клиент-серверная архитектура
Сама концепция клиент-серверной архитектуры заключается в разделении некоторых зон ответственности: в разделении функций клиента и сервера. Что это означает?
Например, мы разделяем нашу систему так, что клиент (допустим, это мобильное приложение) реализует только функциональное взаимодействие с сервером. При этом сервер реализует в себе логику хранения данных, сложные взаимодействия со смежными системами и т.д.
Что мы этим добиваемся и как могло бы быть иначе? Давайте представим, что клиент и сервер у нас объединены. Тогда, если мы говорим о мобильном приложении, каждое мобильное приложение каждого клиента должно было бы быть абсолютно самодостаточной единицей. И тогда, поскольку у нас единого сервера нет для получения/отправки информации, у нас получилась бы какая-то сеть единообразных компонентов – например, мобильные приложения общались бы друг с другом – такая распределённая сеть равноценных узлов.
Такие системы в реальной жизни есть и можно найти их примеры. Например, в блокчейне. Тем не менее, в случае с REST мы говорим о том, что разделяем ответственность. Например, отображение информации, её обработку и хранение.
Клиент-серверная архитектура
Также сервер может иметь базу данных (см. рисунок ниже). В данном случае надо понимать, что пара «сервер и БД» тоже будет парой «клиент-сервер». Только в данном случае сервером будет БД, а сам сервер — клиентом.
Трёхзвенная архитектура
Что дает клиент-серверная архитектура и зачем она нужна?
Во-первых, клиент-серверная архитектура дает нам определённую масштабируемость: есть сервер, есть единая точка обработки запросов. При необходимости выдерживать большую нагрузку мы можем поставить несколько серверов. Также к нему можно подключать достаточно большое количество клиентов (сколько сможет выдержать). Таким образом, клиент-серверная архитектура позволяет добиться масштабируемости.
Во-вторых, REST даёт определённую простоту поддержки. Если мы хотим изменить логику обработки информации на сервере, то выполним эти изменения на сервере. В данном случае мы можем и не менять каждого клиента, как если бы они были абсолютно равноценной сетью.
Конечно, есть и минусы. В случае с клиент-серверной архитектурой мы понимаем, что у нас есть единая точка отказа в виде сервера. Если отказал сервер и у нас нет дополнительных инстансов, то для нас это будет означать неработоспособность системы.
Также потенциально может увеличиться нагрузка, поскольку часть логики мы вынесли с клиента на сервер. Клиент будет совершать меньше каких-либо действий самостоятельно, соответственно, у нас возрастёт количество запросов между клиентом и сервером.
Принцип 2. Stateless
Принцип заключается в том, что сервер не должен хранить у себя информацию о сессии с клиентом. Он должен в каждом запросе получать всю информацию для обработки.
Пример реализации принципа Stateless. Запрос погоды на 20.06 в Москве
Представим, что у нас есть некоторый сервис прогноза погоды, в котором уже реализована клиент-серверная архитектура, и мы хотим получить сообщение о прогнозе погоды на завтра.
Что мы делаем в случае, если мы работаем с Stateless? Мы отправляем запрос «Какая погода?», отправляем место, где хотим погоду узнать, и дату. Соответственно, прогноз погоды отвечает нам — «Будет жарко».
Если я захочу узнать, какая будет погода через день, то опять укажу место, где хочу узнать погоду, укажу другую дату. Сервер получит этот запрос, обработает и сообщит мне, что там уже будет очень жарко.
Пример реализации принципа Stateless. Запрос погоды на 21.06 в Москве
Рассмотрим ситуацию: что было бы, если бы у нас не было Stateless? В таком случае у нас бы был Stateful. В этом случае сервер хранит информацию о предыдущих обращениях клиента, хранит информацию о сессии, какую-то часть контекста взаимодействия с клиентом. А затем может использовать эту информацию при обработке следующих запросов.
Приведём пример на рисунке:
Пример реализации принципа Stateful
Я всё так же хочу узнать, какая погода будет завтра: отправляю запрос, сервер его обрабатывает, формирует ответ и, помимо того, что он возвращает ответ клиентам, он еще сохраняет какую-то информацию (часть или всю) о том, какой запрос он получил. В случае, если я захочу узнать, какая погода будет через день, я могу сделать такой вызов: «А завтра?». Не сообщая ничего о месте и о дате.
В этом случае у сервера хранится некоторый контекст. Он понимает, что я у него спрашиваю про 21-е число и могу дать ответ на основе информации, хранимой у него в БД или в кэше. Один из примеров, где можно встретить подход Stateful в жизни — это работа с FTP-сервером.
Вернёмся к Statless-подходу. Почему в REST-архитектуре мы должны использовать именно Statless-подход?
Какие он даёт плюсы?
Уменьшение времени обработки запроса,
Возможность использовать кэширование.
В первую очередь, это масштабирование сервера. Если каждый запрос содержит в себе абсолютно весь контекст, необходимый для обработки, то можно, например, клонировать сервер-обработчик: вместо одного поставить десять таких. Мне будет абсолютно неважно, в какой из этих клонов придёт запрос. Если бы они хранили состояние, то либо должны были синхронизироваться, либо мне нужно было бы умело направлять запрос в нужное место.
Помимо этого, появляется простота поддержки. Каждый раз я вижу в логах, какое сообщение приходило от клиента, какой ответ он получал. Мне не нужно дополнительно узнавать о том, какое состояние хранил сервер.
Также подход Stateless позволяет использовать кэширование.
Какие проблемы может создать Stateless-подход?
Усложнение логики клиента (именно на стороне клиента нам нужно хранить всю информацию о состоянии, о допустимых действиях, о недопустимых действиях и подобных вещах).
Увеличение нагрузки на сеть (каждый раз мы передаём всю информацию, весь контекст. Таким образом, больше информации гоняем по сети).
Принцип 3. Кэширование
В оригинале этот принцип говорит нам о том, что каждый ответ сервера должен иметь пометку, можно ли его кэшировать.
Что такое кэширование?
Представим, что у нас всё так же есть сервис по прогнозу погоды, есть клиент, с которым взаимодействуют. Сам по себе этот сервис погоду не определяет. Погоду определяет метеостанция, с которой он связывается с помощью специальных удалённых вызовов. Что происходит, когда мы используем кэширование?
Например, клиент обратился к серверу с запросом «Хочу узнать погоду». Что делает сервер?
Если мы его только запустили и используем кэширование или если мы не используем кэширование вообще — сервер обратится к метеостанции, а она вернёт ему ответ. Перед тем, как сервер ответит клиенту, он должен сохранить эту информацию в кэше. И только потом вернуть ответ. Для чего?
Когда клиент в следующий раз отправит ровно такой же запрос, сервер сможет не обращаться к метеостанции. Он сможет извлечь прогноз из кэша и вернуть ответ клиенту.
Пример реализации архитектуры с использованием кэширования
Чего мы добились? Мы убрали одну часть взаимодействия между сервером и метеостанцией. Зачем нам это нужно? Это нужно и полезно, если у сервера часто запрашивают одинаковую информацию. Например, кэширование активно используется на новостных сайтах или в соцсетях (на веб-ресурсах, к которым происходит много обращений).
Какие у кэширования плюсы?
Уменьшение количества сетевых взаимодействий.
Уменьшение нагрузки на системы (не грузим их дополнительными запросами).
В каких-то случаях одинаковых обращений будет не так много. Тогда кэширование использовать нет смысла.
При этом важно понимать, что кэширование — это совсем не простая штука. Она бывает достаточно сложна и нетривиальна в реализации.
Также мы должны учитывать, что если отдаём какие-то данные, которые сохранили раньше, то важно помнить, что эти данные могли уже устареть.
В каких-то случаях это может быть приемлемо, но в каких-то случаях — абсолютно недопустимо. Соответственно, стоит ли использовать кэширование — всегда нужно обдумывать на конкретном примере.
Принцип 4. Единообразие интерфейса. HATEOAS
Hypermedia as the Engine of Application State (HATEOAS) — одно из ограничений REST, согласно которому сервер возвращает не только ресурс, но и его связи с другими ресурсами и действия, которые можно с ним совершить.
Рассмотрим пример. Возьмём HTTP-запрос, в котором я хочу получить определенный ресурс:
Пример запроса ресурса
Здесь мы используем HTTP-глагол GET, то есть хотим получить ресурс. Обращаемся к некоторому счёту с номером 12345.
Если бы мы не использовали подход HATEOAS, то получили бы примерно такой XML-ответ:
Пример ответа без использования принципа HATEOAS
Здесь указан номер счёта, баланс и валюта.
Что же предлагает HATEOAS? Если бы мы с учётом этого ограничения выполняли бы этот запрос, то в ответе получим не только информацию об этом объекте, но и все те действия, которые мы можем с ним совершить. И, если бы у него были бы какие-то важные связанные объекты, мы получили бы ещё и ссылки на них.
Пример ответа с использованием принципа HATEOAS
Получая такие ответы, клиент самостоятельно понимает, какие конкретные действия он может совершать над этим объектом и какую ещё информацию о связанных объектах он может получить. Мы даём клиентскому приложению намного больше информации и свободы действий. Логика клиента становится более гибкой, но при этом и более сложной.
Главный плюс этого подхода — клиент становится очень гибким в плане изменений на сервере с точки зрения изменения допустимых действий, изменения модели данных и т.д.
В качестве обратной стороны медали мы получаем сильное усложнение логики, в первую очередь, клиента. Это может потянуть за собой и усложнение логики на сервере, потому что такие ответы нужно правильно формировать. Фактически ответственность за действия, которые совершает клиент, мы передаём на его же сторону. Мы ослабляем контроль валидности совершаемых операций на стороне сервера.
Принцип 5. Layered system (слоистая архитектура)
В предыдущих схемах мы рассматривали сторону клиента и сторону сервера, но не думали, что между ними могут быть посредники.
В реальной жизни между ними могут быть, к примеру, proxy-сервера, роутеры, балансировщики — все, что угодно. И то, по какому пути запрос проходит от клиента до сервера, мы часто не можем знать.
Концепция слоистой архитектуры заключается в том, что ни клиент, ни сервер не должны знать о том, как происходит цепочка вызовов дальше своих прямых соседей.
Модель слоистой архитектуры
Знания балансировщика в этой схеме об участниках конкретно этой цепочки вызовов должны заканчиваться proxy-сервером слева и сервером справа. О клиенте он уже ничего не знает.
Если изменяется поведение proxy-сервера (балансировщика, роутера или чего-то ещё), это не должно повлечь изменения для клиентского приложения или для сервера. Помещая их в эту цепочку вызовов, мы не должны замечать никакой разницы. Это позволяет нам изменять общую архитектуру без доработок на стороне клиента или сервера.
Увеличение нагрузки на сеть (больше участников и больше вызовов, чем если бы мы шли один раз от клиента до сервера напрямую).
Увеличение времени получения ответа (из-за появления дополнительных участников).
Принцип 6. Code on done (код по требованию)
Идея передачи некоторого исполняемого кода (по сути какой-то программы) от сервера клиенту.
Модель архитектуры, реализующей принцип «Код по запросу»
Представьте, что клиент — это, например, обычный браузер. Клиент отправляет некоторый запрос и ждёт ответа — страницу с определённым интерактивом (например, должен появляться фейерверк в том месте, где пользователь кликает кнопкой мышки). Это всё может быть реализовано на стороне клиента.
Либо клиент, запрашивая данную страницу приветствия, получит в ответ от сервера не просто HTML-код для отображения, а ещё программу, которую он сам и исполнит. Получается, что сервер передаёт исходный код клиенту, а тот его выполняет.
Что мы за счёт этого получаем? Отчасти, это схоже с принципом HATEOAS. Мы позволяем клиенту стать гибче. Если мы захотим изменить цвет фейерверка, то нам не нужно вносить изменений на клиенте — мы можем сделать это на сервере, а затем передавать клиенту. Пример такого языка — javascript.
Насколько же сходятся идеи, которые вложил Рэй Филдинг в концепцию REST, с восприятием REST аналитиками?
Давайте рассмотрим наиболее частые заблуждения, которые вы можете встретить относительно концепции REST.
1. Ограничения REST опциональны (необязательны)
С точки зрения создателя этой концепции существует ровно одно необязательное ограничение — код по требованию. Все остальные ограничения должны выполняться. Если одно из них не выполняется — это уже не REST-подход.
2. REST — протокол передачи данных
REST — это не протокол передачи данных. Он не определяет правила о том, как мы должны передавать запросы, какая у них должна быть структура, что мы должны возвращать в ошибках. Единственное, что косвенно можно было бы приписать — это указание на то, что каждый ответ сервера должен содержать информацию о том, можно ли его кэшировать.
Но, в целом, REST — это концепция, парадигма, но не протокол. В отличие от HTTP, который действительно является протоколом.
3. REST — это всегда HTTP
С одной стороны, ни один из архитектурных принципов REST не говорит нам о том, какой транспорт мы должны использовать — HTTP или очереди.
Но при этом в жизни очень часто встречаются люди, для которых REST и HTTP — это аксиома.
Поэтому, если сказать человеку, что REST — это необязательно HTTP, то вас могут посчитать сумасшедшими.
Почему же все считают, что REST — это HTTP? Здесь нужно сделать ремарку, что одним из главных авторов протокола HTTP — это Рэй Филдинг, автор концепции REST. Рэй Филдинг стремился спроектировать HTTP так, чтобы с помощью него концепцию REST было максимально удобно реализовывать.
4. REST — это обязательно JSON
Почему так сложилось? Главная причина в том, что какое-то время назад сервисы вида JSON over HTTP стали противопоставлять SOAP. JSON одновременно стал популярным и стал антагонистом XML, как SOAP подходу. JSON использовался, потому что это не SOAP.
Модель зрелости REST-сервисов
Ричардсон выделил уровни зрелости REST-сервисов. Выделение происходило исходя из подхода, что REST — это, с точки зрения протокола, всё-таки HTTP. Соответственно, он спроектировал модель, по которой можно понять: насколько сервис REST или не REST.
Уровень 0
В первую очередь, он выделил нулевой уровень. К нему относятся любые сервисы, которые в качестве транспорта используют HTTP и какой-то формат представления данных. Например, когда мы говорим про JSON over HTTP – мы говорим про нулевой уровень.
Если более наглядно «пощупать ручками» с точки зрения использования протокола HTTP, то можно представить, что мы выставляем некоторый API. Мы начинаем с того, что объявляем единый путь для отправки команд и всегда используем один и тот же HTTP-глагол для совершения абсолютно любых действий с любыми объектами. Например: создай вебинар, запиши вебинар, удали вебинар и т.д. То есть мы всегда используем один и тот же URL и всегда используем один и тот же HTTP-метод, обычно POST.
Как один из примеров:
Пример 0-го уровня соответствия REST
Уровень 1
Следующий уровень — первый. Мы уже научились использовать разные ресурсы и делаем это не по одному URL. Но при этом всё ещё игнорируем HTTP-глаголы.
Мы просто разделяем явно наши объекты, как некоторые ресурсы. Например: спикер, курс, вебинар. Но, независимо от того, что мы хотим сделать — удалить, создать, редактировать, мы всё равно используем один и тот же HTTP-глагол POST.
Пример 1-го уровня соответствия REST
Уровень 2
Второй уровень — это когда мы начинаем правильно с точки зрения спецификации HTTP-протокола использовать HTTP-глаголы.
Например, если есть спикер, то, чтобы создать спикера и получить информацию о нём, я использую соответствующий глагол: GET, POST. Когда хочу создать или удалить спикера — я использую глаголы: PUT, DELETE.
По сути, второй уровень зрелости — это то, что чаще всего называют REST.
Надо понимать, что, с точки зрения изначальной концепции, если мы дошли до второго уровня зрелости, то это еще не означает, что мы спроектировали REST-систему/ REST-сервис. Но в очень распространённом понимании соответствие 2-ому уровню часто называют RESTfull сервисом.
RESTfull-сервис — это такой сервис, который спроектирован с учётом REST-ограничений. Хотя, в целом, правильнее сервис такого уровня зрелости называть HTTP-сервисом или HTTP-API, нежели REST-API.
Пример 2-го уровня соответствия REST
Уровень 3
Третий уровень зрелости — это уровень, в котором мы начинаем использовать концепцию HATEOAS. Когда мы передаём информацию, ресурсы, мы сообщаем потребителям (клиентам) о том, какие ещё действия необходимо совершить ресурсу, а также связи с другими ресурсами.
Пример 3-го уровня соответствия REST
Выводы, которые мы можем сделать из модели зрелости
Итак, как нам эта модель может помочь понять то, что наши коллеги называют RESTом в каждой отдельно взятой компании? REST у вас или не REST?
Первая распространенная трактовка термина REST — всё, что передаётся в виде JSON поверх HTTP.
Вторая, не менее популярная версия, REST — это сервис второго уровня зрелости, то есть HTTP-API, составленное в соответствии со спецификацией HTTP-протокола. Если мы правильно выделяем ресурсы, правильно используем HTTP-глаголы, а также выполняем некоторые требования HTTP-протокола, то у нас REST.
Что называют RESTом?
Подведём итоги
Во-первых, у каждого свой REST. Мнения о том, что такое REST, часто разнятся. Когда мы работаем с новыми проектами, новыми коллегами или специалистами, очень важно понять, что именно ваш коллега называет RESTом. Это полезно для того, чтобы на одном из этапов проектирования или разработки не оказалось, что мы половину проекта говорили о разных вещах.
Во-вторых, принципы REST мы часто применяем в жизни. Они очень полезны для осмысления. Кэширование, STATELESS и STATEFUL, клиент-серверная модель или код по требованию — это те вещи, которые аналитику полезно знать для понимания.
Третье — это то, что парадигма REST помогает нам выявить и определить важнейшие свойства архитектуры — масштабируемость, производительность и т.д.
1. Способы описания API
2. Инструменты для тестирования API