Архитектура и принципы REST. Что значит RESTful? Что такое SOAP? Какие проблемы решает GraphQL?
Что такое REST?
REST - это акроним от Representational state transfer (передача состояния представления).
Сервер может считаться RESTful, если он соответствует принципам REST.
Принципы REST:
1. Независимость от состояния (Statelessness)
Сервер не должен запоминать состояние пользователя между запросами — в каждом запросе передаётся информация, идентифицирующая пользователя (например, token, полученный через OAuth-авторизацию) и все параметры, необходимые для выполнения операции.
Независимость от состояния означает, что данные, возвращаемые определенным вызовом API, не должны зависеть от вызовов, сделанных ранее.
2. Многоуровневая архитектура (Layered System)
Многоуровневая архитектура означает, что клиенту всё равно, является ли отвечающий сервер конечным в цепочке или нет. Что даёт отличную возможность для кэширования и распределения нагрузки. Кроме того, многоуровневая архитектура говорит и о том, что внутри сервера всё делится на компоненты, которые не обязаны быть связаны напрямую друг с другом: например, есть метод, который пишет какие-то данные в файл, и есть метод, который записывает что-то в базу данных. Они могут быть не связаны друг с другом, но при этом вызываются из третьей компоненты, которая и содержит в себе логику того, как они должны взаимодействовать.
3. Единый унифицированный программный интерфейс
К примеру для получения списка фильмов вы используете URL вида: /videos.com/movies, а для получения информации о конкретном фильме ваш URL будет: /videos.com/movies/1)
4. Кэшируемая архитектура (Cacheable)
Ответ сервера может быть кэширован на определенный период времени и использоваться повторно без новых запросов к серверу. Это касается, в основном, GET-запросов, потому что POST-запросы кэшировать было бы довольно странно.
5. Удобное представление данных
В качестве представления данных объекта передаются данные в формате JSON или XML. Сейчас почти везде используется JSON, который де-факто уже стал стандартом для обмена данными между клиентом и сервером. XML, хотя и даёт возможность, структурировать информацию более хорошо, чем JSON, но при этом является слишком раздутым на выходе. Обмен данными в формате XML является слишком медленным, по сравнению, с JSON.
HTTP-методы и их обозначения
- GET — для получения (чтение)
- POST — для создания
- PUT — для изменения
- PATCH — для частичного изменения
- DELETE — для удаления
Статус-коды HTTP
Статус коды указывают на результат HTTP запроса.
1ХХ
— информационный2ХХ
— успешное выполнение3ХХ
— перенаправление4ХХ
— ошибка клиента5ХХ
— ошибка сервера
Аналоги REST
До REST использовался протокол SOAP (Simple Object Access Protocol — простой протокол доступа к объектам). По сути, SOAP является расширением XML-RPC (RPC — это Remote Procedure Call, Удалённый вызов процедур). Обычно, его используют поверх HTTP-протокола. Главный минус SOAP как раз в том, что XML увеличивает объём передаваемых данных, а значит и снижает скорость их обработки.
Структура SOAP-сообщения выглядит так:
- Envelope — корневой элемент, который определяет сообщение и пространство имен, использованное в документе.
- Header — содержит атрибуты сообщения, например: информация о безопасности или о сетевой маршрутизации.
- Body — содержит сообщение, которым обмениваются приложения.
- Fault — необязательный элемент, который предоставляет информацию об ошибках, которые произошли при обработке сообщений.
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <getProductDetails xmlns="http://warehouse.example.com/ws"> <productID>12345</productID> </getProductDetails> </soap:Body> </soap:Envelope>
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <getProductDetailsResponse xmlns="http://warehouse.example.com/ws"> <getProductDetailsResult> <productID>12345</productID> <productName>Стакан граненый</productName> <description>Стакан граненый. 250 мл.</description> <price>9.95</price> <currency> <code>840</code> <alpha3>USD</alpha3> <sign>lt;/sign> <name>US dollar</name> <accuracy>2</accuracy> </currency> <inStock>true</inStock> </getProductDetailsResult> </getProductDetailsResponse> </soap:Body> </soap:Envelope>
У REST тоже есть свои болевые точки, как правило, когда об этом говорят, упоминают обычно то, что приходится делать довольно большое количество запросов, чтобы добиться нужного эффекта. Например, API отдаёт список постов из социальной сети с лайками и комментариями, в которых нужно ещё и вложить ссылки на аватарки пользователей, кроме самой информации о комментариях, но у разных клиентов разная скорость загрузки, поэтому в мобильном приложении, к примеру, такие ответы будут загружаться дольше, чем на десктопе, из чего следует потребность появления второго эндпоинта, который будет возвращать посты без лайков и комментариев, а те, в свою очередь, будут подгружаться по необходимости. Таким образом, клиенту придётся делать два запроса вместо одного. Для решения подобных проблем в Facebook был придуман синтаксис описания запросов GraphQL, который нужен для того, чтобы клиент сам говорил серверу о том, какие данные ему нужны, а сервер, в свою очередь, отдавал ему именно то, что нужно и в том формате, в котором нужно. Кроме того, GraphQL является типизированным, что позволяет исключить ошибки в непонимании типов данных, которые приходят с сервера.
Не стоит бояться, что GraphQL был придуман в большом и страшном Facebook, поскольку это просто формат, реализацию сервера же можно использовать какую угодно. В том числе и написать свою.
В общих чертах, клиент-серверное взаимодействие в GraphQL строится так:
Сам GraphQL сервер состоит из трёх компонентов: Запрос, Распознаватель, Схема. Схема отвечает за структуру данных, над которыми происходят операции, она является типизированной. Распознаватели отвечают за то, откуда нужно получать те или иные данные, а запрос то, в каком виде эти данные хочет клиент.