REST API
REST (от англ. Representational State Transfer — «передача состояния представления») — архитектурный стиль взаимодействия компонентов распределённого приложения в сети.
REST представляет собой согласованный набор ограничений, учитываемых при проектировании распределённой системы и способствующих производительности и упрощению её архитектуры. Термин REST был введен в 2000 году Роем Филдингом, одним из авторов протокола HTTP.
Системы, выполняющие все обязательные ограничения REST, называются RESTful-системами. При этом «официального» стандарта для RESTful веб-API не существует.
В общем случае REST является очень простым интерфейсом управления информацией без использования каких-то дополнительных внутренних прослоек. Каждая единица информации однозначно определяется глобальным идентификатором URI.
Отсутствие дополнительных внутренних прослоек означает передачу данных в том же виде, что и сами данные.
Каждую единицу информации однозначно определяет URI – это значит, что URI по сути является первичным ключом для единицы данных. Т.е. например третья книга с книжной полки будет иметь вид /books/3, а 35 страница в этой книге — /books/3/pages/35. Отсюда и получается строго заданный формат. Причем совершенно не имеет значения, в каком формате находятся данные – это может быть и HTML, и отсканированная копия в виде jpeg-файла, и документ Microsoft Word.
Как происходит управление информацией сервиса – это целиком и полностью основывается на протоколе передачи данных. По сути сейчас весь REST основан на протоколе HTTP/HTTPS. REST-запрос к серверу представляет собой обычный HTTP-запрос, а необходимые данные передаются в качестве параметров запроса.
Так вот, для HTTP действие над данными задается с помощью методов:
- GET (получить),
- PUT (добавить, заменить),
- POST (добавить, изменить, удалить),
- DELETE (удалить).
Таким образом, действия CRUD (Create-Read-Updtae-Delete) могут выполняться как со всеми 4-мя методами, так и только с помощью GET и POST.
Вот как это будет выглядеть на примере:
GET /books/ — получить список всех книг
GET /books/3/ — получить книгу номер 3
PUT /books/ — добавить книгу (данные в теле запроса)
POST /books/3 – изменить книгу (данные в теле запроса)
DELETE /books/3 – удалить книгу
Современные REST-системы удовлетворяют следующим правилам:
- Явное использование HTTP-методов
- Отсутствие состояния
- Представление URI в виде директорий
- Передача данных в виде JSON, XML или обеих сразу
История термина
Хотя данная концепция лежит в самой основе Всемирной паутины, термин «REST» был введён Роем Филдингом, одним из создателей протокола «HTTP», лишь в 2000 году. В своей диссертации «Architectural Styles and the Design of Network-based Software Architectures» он подвёл теоретическую основу под способ взаимодействия клиентов и серверов во Всемирной паутине, абстрагировав его и назвав «передачей представительного состояния» («Representational State Transfer»). Филдинг описал концепцию построения распределённого приложения, при которой каждый запрос (REST-запрос) клиента к серверу содержит в себе исчерпывающую информацию о желаемом ответе сервера (желаемом представительном состоянии), и сервер не обязан сохранять информацию о состоянии клиента («клиентской сессии»).
Требования к архитектуре REST
Существует шесть обязательных ограничений для построения распределённых REST-приложений.
Обязательными условиями являются:
- Модель клииент-сервер
- Отсутствие состояния
- Кэширование
- Единообразие интерфейса
- Наличие слоёв
- Код по требованию (необязатиельное)
1. Модель клиент-сервер
Первым ограничением, применимым к гибридной модели, является приведение архитектуры к модели клиент-сервер. Разграничение потребностей является принципом, лежащим в основе данного накладываемого ограничения. Отделение потребности интерфейса клиента от потребностей сервера, хранящего данные, повышает переносимость кода клиентского интерфейса на другие платформы, а упрощение серверной части улучшает масштабируемость. Наибольшее же влияние на всемирную паутину, пожалуй, имеет само разграничение, которое позволяет отдельным частям развиваться независимо друг от друга, поддерживая потребности в развитии интернета со стороны различных организаций.
2. Отсутствие состояния
Протокол взаимодействия между клиентом и сервером требует соблюдения следующего условия: в период между запросами клиента никакая информация о состоянии клиента на сервере не хранится (Stateless protocol или «протокол без сохранения состояния»). Все запросы от клиента должны быть составлены так, чтобы сервер получил всю необходимую информацию для выполнения запроса. Состояние сессии при этом сохраняется на стороне клиента[2]. Информация о состоянии сессии может быть передана сервером какому-либо другому сервису (например, в службу базы данных) для поддержания устойчивого состояния, например, на период установления аутентификации. Клиент инициирует отправку запросов, когда он готов (возникает необходимость) перейти в новое состояние.
Во время обработки клиентских запросов считается, что клиент находится в переходном состоянии. Каждое отдельное состояние приложения представлено связями, которые могут быть задействованы при следующем обращении клиента.
3. Кэширование
Как и во Всемирной паутине, клиенты, а также промежуточные узлы, могут выполнять кэширование ответов сервера. Ответы сервера, в свою очередь, должны иметь явное или неявное обозначение как кэшируемые или некэшируемые с целью предотвращения получения клиентами устаревших или неверных данных в ответ на последующие запросы. Правильное использование кэширования способно частично или полностью устранить некоторые клиент-серверные взаимодействия, ещё больше повышая производительность и масштабируемость системы.
4. Единообразие интерфейса
Наличие унифицированного интерфейса является фундаментальным требованием дизайна REST-сервисов[2]. Унифицированные интерфейсы позволяют каждому из сервисов развиваться независимо.
К унифицированным интерфейсам предъявляются следующие четыре ограничительных условия[9][10]:
- Идентификация ресурсов
Все ресурсы идентифицируются в запросах, например, с использованием URI в интернет-системах. Ресурсы концептуально отделены от представлений, которые возвращаются клиентам. Например, сервер может отсылать данные из базы данных в виде HTML, XML или JSON, ни один из которых не является типом хранения внутри сервера. - Манипуляция ресурсами через представление
Если клиент хранит представление ресурса, включая метаданные — он обладает достаточной информацией для модификации или удаления ресурса. - «Самоописываемые» сообщения
Каждое сообщение содержит достаточно информации, чтобы понять, каким образом его обрабатывать. К примеру, обработчик сообщения (parser), необходимый для извлечения данных, может быть указан в списке MIME-типов[2]. - Гипермедиа как средство изменения состояния приложения (HATEOAS)
Клиенты изменяют состояние системы только через действия, которые динамически определены в гипермедиа на сервере (к примеру, гиперссылки в гипертексте). Исключая простые точки входа в приложение, клиент не может предположить, что доступна какая-то операция над каким-то ресурсом, если не получил информацию об этом в предыдущих запросах к серверу. Не существует универсального формата для предоставления ссылок между ресурсами, Web Linking (RFC 5988 -> RFC 8288) и JSON Hypermedia API Language являются двумя популярными форматами предоставления ссылок в REST HYPERMEDIA сервисах.
5. Слои
Клиент обычно не способен точно определить, взаимодействует он напрямую с сервером или же с промежуточным узлом, в связи с иерархической структурой сетей (подразумевая, что такая структура образует слои). Применение промежуточных серверов способно повысить масштабируемость за счёт балансировки нагрузки и распределённого кэширования. Промежуточные узлы также могут подчиняться политике безопасности с целью обеспечения конфиденциальности информации[11].
6. Код по требованию (необязательное ограничение)
REST может позволить расширить функциональность клиента за счёт загрузки кода с сервера в виде апплетов или сценариев. Филдинг утверждает, что дополнительное ограничение позволяет проектировать архитектуру, поддерживающую желаемую функциональность в общем случае, но, возможно, за исключением некоторых контекстов.
Действуя в рамках этих ограничений, система приобретает следующие преимущества:
- Надёжность (за счёт отсутствия необходимости сохранять информацию о состоянии клиента, которая может быть утеряна);
- Производительность (за счёт использования кэша);
- Масштабируемость;
- Прозрачность системы взаимодействия (особенно необходимая для приложений обслуживания сети);
- Простота интерфейсов;
- Портативность компонентов;
- Лёгкость внесения изменений;
- Способность эволюционировать, приспосабливаясь к новым требованиям (на примере Всемирной паутины).