Компьютерные сети
February 27, 2023

Архитектура REST и API

Об архитектурном стиле REST, REST API, RESTful сервисах, ограничениях с ними связанных, ресурсах, их представлении и безопасности.

REST (Representational State Transfer)передача состояния представленияархитектурный стиль взаимодействия компонентов распределённого приложения в сети.

REST API — это способ взаимодействия двух компьютерных систем с использованием технологий HTTP (Hyper Text Transfer Protocol), используемых в веб-браузерах, приложениях и серверах.

Для веб-служб, построенных с учётом REST и выполняющим условия некоторых 5-ти ограничений, применяют термин «RESTful».

В отличие от веб-сервисов на основе SOAP, не существует «официального» стандарта для RESTful веб-API. Дело в том, что REST является архитектурным стилем, в то время как SOAP является протоколом. Несмотря на то, что REST не является стандартом сам по себе, большинство RESTful-реализаций используют такие стандарты, как HTTP, URL, JSON.

Оглавление:

Свойства Архитектуры REST

Свойства архитектуры, которые зависят от ограничений, наложенных на REST-системы:

  • Производительность — взаимодействие компонентов системы может являться доминирующим фактором производительности и эффективности сети с точки зрения пользователя.
  • Масштабируемость — для обеспечения большого числа компонентов и взаимодействий компонентов.

Рой Филдинг — один из главных авторов спецификации протокола HTTP, описывает влияние архитектуры REST на масштабируемость следующим образом:

  • Простота унифицированного интерфейса.
  • Открытость компонентов к возможным изменениям для удовлетворения изменяющихся потребностей (даже при работающем приложении).
  • Прозрачность связей между компонентами системы для сервисных служб.
  • Переносимость компонентов системы путем перемещения программного кода вместе с данными.
  • Надёжность, выражающаяся в устойчивости к отказам на уровне системы при наличии отказов отдельных компонентов, соединений или данных.

Требования к архитектуре REST

Существует пять обязательных ограничений для построения распределённых REST-приложений.

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

Если сервис-приложение нарушает одно из этих 5-ти ограничительных условий, данную систему нельзя считать RESTful-системой.

Ограничения:

1. Модель клиент-сервер

Клиент-серверный способ взаимодействия, где Система-А отправляет HTTP-запрос на URL-адрес, размещенный в Системе-Б, который возвращает ответ.

Разграничение потребностей является принципом, лежащим в основе данного накладываемого ограничения. Отделение потребности интерфейса клиента от потребностей сервера, хранящего данные, повышает переносимость кода клиентского интерфейса на другие платформы, а упрощение серверной части улучшает масштабируемость.

2. Отсутствие состояния

REST не имеет состояния: клиентский запрос должен содержать всю информацию, необходимую для ответа. Другими словами, запрос обрабатывается каждый раз с чистого листа, и если сделать два или более HTTP-запросов в любом порядке, то будут получены одни и те же ответы (если API не был предназначен для возврата случайных ответов).

Протокол взаимодействия между клиентом и сервером требует соблюдения следующего условия: в период между запросами клиента никакая информация о состоянии клиента на сервере не хранится (Stateless protocol или «протокол без сохранения состояния»). Все запросы от клиента должны быть составлены так, чтобы сервер получил всю необходимую информацию для выполнения запроса.

Состояние сессии при этом сохраняется на стороне клиента. Информация о состоянии сессии может быть передана сервером какому-либо другому сервису (например, в службу базы данных) для поддержания устойчивого состояния, например, на период установления аутентификации. Клиент инициирует отправку запросов, когда он готов (возникает необходимость) перейти в новое состояние.

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

3. Кэширование

Как и во Всемирной паутине, клиенты, а также промежуточные узлы, могут выполнять кэширование ответов сервера. Ответы сервера, в свою очередь, должны иметь явное или неявное обозначение как кэшируемые или некэшируемые с целью предотвращения получения клиентами устаревших или неверных данных в ответ на последующие запросы. Правильное использование кэширования способно полностью или частично устранить некоторые клиент-серверные взаимодействия, ещё больше повышая производительность и расширяемость системы.

4. Единообразие интерфейса

Наличие унифицированного интерфейса (приведенного к общему стандарту) является фундаментальным требованием дизайна REST-сервисов. Унифицированные интерфейсы позволяют каждому из сервисов развиваться независимо.

К унифицированным интерфейсам предъявляются следующие четыре ограничительных условия:

Идентификация ресурсов

  • Все ресурсы идентифицируются в запросах, например, с использованием URI в интернет-системах. Ресурсы концептуально отделены от представлений, которые возвращаются клиентам. Например, сервер может отсылать данные из базы данных в виде HTML, XML или JSON, ни один из которых не является типом хранения внутри сервера.

Манипуляция ресурсами через представление

  • Если клиент хранит представление ресурса, включая метаданные — он обладает достаточной информацией для модификации или удаления ресурса.

«Самоописываемые» сообщения

  • Каждое сообщение содержит достаточно информации, чтобы понять, каким образом его обрабатывать. К примеру, обработчик сообщения (parser), необходимый для извлечения данных, может быть указан в списке MIME-типов.

Гипермедиа как средство изменения состояния приложения (HATEOAS)

  • Клиенты изменяют состояние системы только через действия, которые динамически определены в гипермедиа на сервере (к примеру, гиперссылки в гипертексте). Исключая простые точки входа в приложение, клиент не может предположить, что доступна какая-то операция над каким-то ресурсом, если не получил информацию об этом в предыдущих запросах к серверу. Не существует универсального формата для предоставления ссылок между ресурсами, Web Linking (RFC 5988 -> RFC 8288) и JSON Hypermedia API Language являются двумя популярными форматами предоставления ссылок в REST HYPERMEDIA сервисах.

5. Слои

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

6. Код по требованию (необязательное ограничение)

REST может позволить расширить функциональность клиента за счёт загрузки кода с сервера в виде апплетов или сценариев. Филдинг утверждает, что дополнительное ограничение позволяет проектировать архитектуру, поддерживающую желаемую функциональность в общем случае, но, возможно, за исключением некоторых контекстов.

Пример REST API

Пример запроса к Open Trivia REST API (это общедоступный RESTful API) через браузер:

https://opentdb.com/api.php?amount=1&category=18

Ваш браузер покажет один вопрос викторины в формате JSON с ответами, например:

{
  "response_code": 0,
  "results": [
    {
      "category": "Science: Computers",
      "type": "multiple",
      "difficulty": "easy",
      "question": "What does GHz stand for?",
      "correct_answer": "Gigahertz",
      "incorrect_answers": [
        "Gigahotz",
        "Gigahetz",
        "Gigahatz"
      ]
    }
  ]
}

Ресурсы

В REST под ресурсами понимают любые источники, к которым клиент может обратиться для получения информации или выполнения операций. Ресурсами могут быть, например, объекты базы данных, файлы, изображения, видео, аудио, текстовые документы и другие данные.

Представление ресурсов

Представление ресурса — это формат, в котором он может быть представлен клиенту, например, это может быть формат HTML, XML, JSON, YAML и другие.

Клиент может запросить определенное представление ресурса, указав соответствующий MIME-тип в заголовке Accept.

Accept: application/xml

Сервер должен предоставить запрошенный формат представления ресурса, если он доступен, в другом случае вернуть по умолчанию JSON.

Доступ к ресурсам

Запрос к REST сервису состоит из:

  • endpoint’а,
  • HTTP метода,
  • HTTP заголовков,
  • тела запроса (“body data”/payload).

Каждый ресурс в REST должен быть однозначно идентифицируем посредством уникального идентификатора URI.

URI (Uniform Resource Identifier) — это строка символов, которая идентифицирует определенный ресурс в Интернете, такой как документ, изображение или сервис. В контексте REST, URI используется для определения ресурса и адреса его расположения.

URI parameters и query parameters — это два различных способа передачи параметров в запросах HTTP.

URI (или path) parameters — это параметры, которые передаются в пути URI ресурса, как часть самого пути. Они обычно используются для идентификации конкретных ресурсов. Например, в URI api/users/12/ "12" является URI параметром, который указывает на индентификатор конкретного пользователя.

Query parameters — это параметры, которые передаются в запросе после знака вопроса “?” в URI ресурса. Они обычно используются для фильтрации, сортировки или поиска данных. Например, в URI api/users/?age=25&city=New%20York параметры "age" и "city" являются query параметрами, которые указывают на фильтрацию пользователей, чей возраст равен 25 и которые живут в городе Нью-Йорк.

URI parameters и query parameters могут использоваться вместе в URI запросах, чтобы обеспечить более гибкий и мощный механизм для доступа к REST-ресурсам.

Endpoints — это конечная точка, к которой обращается клиент при выполнении операций с ресурсом. Он представляет конкретный URL, который указывает на ресурс или коллекцию ресурсов, которые клиент хочет получить или изменить.

Таким образом, URI и endpoints — это два термина, которые используются в разных контекстах, но они тесно связаны. URI идентифицирует ресурс, в то время как endpoint представляет конкретный адрес, по которому можно получить доступ к этому ресурсу. Endpoint является частью URI, но сам по себе он представляет конкретный адрес, по которому можно получить доступ к ресурсу.

URI: https://api.example.com/users/123

Endpoint: /users/123

Рассмотрим примеры endpoint’ов:

  • api/users/: Этот endpoint используется для получения списка всех пользователей в системе. Это типичный пример коллекции (collection) в REST API.
  • api/users/12/: Этот endpoint используется для получения информации о конкретном пользователе с идентификатором "12". Здесь "12" - это параметр URI.
  • api/users/12/books/: Этот endpoint используется для получения списка книг, связанных с пользователем с идентификатором "12".
  • api/users/12/books/4: Этот endpoint используется для получения информации о конкретной книге с идентификатором "4", связанной с пользователем с идентификатором "12".

Различие между ними заключается в том, на какую информацию указывает конкретный endpoint.

Таким образом ресурсы можно поделить на:

  • Коллекции ресурсов: Коллекция ресурсов представляет собой группу ресурсов, которые могут быть запрошены как единое целое. Например, коллекция всех пользователей в системе. URL-адрес для коллекции ресурсов будет иметь форму /users, где users - это название коллекции.
  • Конкретные ресурсы: Конкретный ресурс — это один объект в коллекции ресурсов. Он может быть запрошен по идентификатору, который обычно включен в URL-адрес. Например, для получения информации о конкретном пользователе с идентификатором 123, URL-адрес будет иметь форму /users/123, где 123 - это идентификатор пользователя.
  • Вложенные ресурсы: Вложенные ресурсы — это ресурсы, которые находятся внутри других ресурсов. Они обычно используются для представления связей между ресурсами. Например, для получения списка книг, которые принадлежат пользователю с идентификатором 123, URL-адрес будет иметь форму /users/123/books, где books - это вложенный ресурс, который представляет список книг пользователя с идентификатором 123. Кроме того, чтобы получить информацию о конкретной книге с идентификатором 456, URL-адрес будет иметь форму /users/123/books/456, где 456 - это идентификатор книги.

HTTP методы

CRUD — это акроним, который обозначает четыре основных функции, которые могут быть выполнены с помощью базы данных или другого хранилища данных: создание (Create), чтение (Read), обновление (Update) и удаление (Delete).

В REST-архитектуре эти функции реализуются через HTTP методы:

+--------+------------+--------------------+----------------------------------+
| CRUD   | HTTP метод | Операция           | Примечание                       |
| ------ | ---------- | ------------------ | -------------------------------- |
| Read   | GET        | Запрос ресурса     | Не изменяет состояние на сервере.|
| Create | POST       | Создание ресурса   | Данные передаются в теле запроса.|
| Update | PUT/PATCH  | Обновление ресурса | PUT для полного замены ресурса,  |
|        |            |                    | PATCH для частичного обновления  |
|        |            |                    | ресурса.                         |
| Delete | DELETE     | Удаление ресурса   | -                                |
+--------+------------+--------------------+----------------------------------+

Таким образом, с помощью методов HTTP можно выполнить все четыре операции CRUD, которые используются для работы с данными в REST-архитектуре.

HTTP заголовки

При использовании REST API могут использоваться различные заголовки для передачи метаданных или управления поведением запросов и ответов. Некоторые из наиболее распространенных заголовков в REST API:

  1. Content-Type: Определяет тип данных, содержащихся в теле запроса или ответа, например, JSON, XML или HTML. Например, при отправке запроса на создание новой записи (POST) может использоваться заголовок Content-Type: application/json для указания того, что данные, передаваемые в теле запроса, должны быть в формате JSON.
  2. Accept: Определяет типы данных, которые клиент готов принять от сервера в ответе. Например, Accept: application/json может использоваться для запроса данных в формате JSON.
  3. Authorization: Используется для передачи учетных данных (логин и пароль) при доступе к защищенным ресурсам.

Конечно, это не полный список заголовков, которые могут использоваться в REST API, и конкретные заголовки могут варьироваться в зависимости от реализации и потребностей проекта.

Авторизация

Авторизация в REST API — это процесс проверки подлинности запросов к API, который обычно выполняется перед выполнением действий в отношении определенных ресурсов. При работе с RESTful API используют различные методы авторизации для защиты данных и предотвращения несанкционированного доступа.

Ниже приведены некоторые распространенные методы авторизации:

  1. HTTP Basic Authentication: это метод авторизации, в котором клиент отправляет в запросе заголовок Authorization, содержащий base64-кодированную комбинацию логина и пароля. Несмотря на то, что метод довольно прост в использовании, он не является самым безопасным, поскольку авторизационные данные передаются в открытом виде.
  2. API Key: это метод, при котором выдается уникальный ключ, который клиент должен передавать в каждом запросе. Ключи API могут иметь различные уровни доступа, их можно ограничивать по времени или по использованию, а также отзывать в случае утечки.
  3. OAuth: это открытый протокол авторизации, который позволяет приложению получать доступ к ресурсам от имени пользователя без необходимости знать его логин и пароль. Пользователь передает свои данные авторизации OAuth-серверу, который выдает токен, который затем может быть использован для доступа к ресурсам.
  4. JSON Web Tokens (JWT): это метод авторизации, в котором токен с информацией о пользователе и его правах генерируется и подписывается сервером, а затем передается клиенту. При дальнейшей работе с API этот токен отправляется с каждым запросом в заголовке Authorization, и сервер декодирует его, чтобы удостовериться, что запросы приходят от авторизованного пользователя.

Какой метод авторизации использовать, зависит от конкретной задачи, уровня безопасности данных и требований к доступу. В любом случае, перед тем, как реализовывать авторизацию, нужно провести анализ угроз и выбрать оптимальный метод защиты.

Безопасность

Некоторые основные меры безопасности, которые могут быть применены при разработке REST API, включают в себя:

  1. Аутентификация и авторизация: Аутентификация используется для проверки подлинности пользователя, а авторизация определяет, какие операции разрешены для данного пользователя. Хорошо проработанная система аутентификации и авторизации гарантирует, что доступ к ресурсам будет только у разрешенных пользователей.
  2. HTTPS: это шифрованный протокол, который обеспечивает безопасную передачу данных между клиентом и сервером. Использование HTTPS обеспечивает конфиденциальность, целостность и аутентификацию данных.
  3. Защита от CSRF-атак: CSRF (межсайтовая подделка запроса) — это тип атаки, при которой злоумышленник создает запрос от имени другого пользователя без его ведома. Для защиты от таких атак можно использовать механизмы, такие как токены CSRF.
  4. Ограничение скорости запросов: Ограничение скорости запросов может помочь предотвратить атаки, такие как DDoS, которые могут нарушить работу сервера.
  5. Обработка ошибок: Обработка ошибок должна быть проработана так, чтобы она не раскрывала конфиденциальную информацию.
  6. Хранение паролей: Хранение паролей должно быть сделано таким образом, чтобы они не были доступны для чтения злоумышленникам.
  7. Аудит и логирование: Логирование и аудит могут помочь выявить подозрительную активность и принять меры для ее предотвращения.

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

Преимущества и недостатки REST

Преимущества REST:

  1. Простота в использовании: REST веб-сервисы используют протокол HTTP, который уже широко используется в Интернете, что упрощает их использование и интеграцию в различные приложения.
  2. Масштабируемость и надежность: RESTful веб-сервисы являются масштабируемыми, так как они не хранят состояния, что означает, что каждый запрос можно обрабатывать независимо.
  3. Гибкость: REST веб-сервисы могут использоваться с различными языками программирования и фреймворками. Лёгкость внесения изменений.
  4. Кэширование: RESTful веб-сервисы легко кэшируются, что повышает производительность приложений.
  5. Безопасность: RESTful веб-сервисы могут быть защищены различными механизмами безопасности, такими как SSL и OAuth.
  6. Способность эволюционировать, приспосабливаясь к новым требованиям (на примере Всемирной паутины).

Недостатки REST:

  1. Отсутствие стандарта: RESTful веб-сервисы могут быть реализованы с различными уровнями согласованности и с различными форматами данных, что может приводить к трудностям при разработке и интеграции приложений.
  2. Недостаточная гибкость: RESTful веб-сервисы не всегда обладают достаточной гибкостью для решения сложных задач, таких как транзакции.
  3. Ограничения протокола HTTP: Протокол HTTP имеет некоторые ограничения, которые могут ограничивать возможности RESTful веб-сервисов, такие как максимальный размер передаваемых данных или ограниченный набор методов HTTP.
  4. Потенциальная производительность: RESTful веб-сервисы могут иметь сниженную производительность в некоторых случаях, таких как передача больших объемов данных или выполнение сложных запросов.

Источники:

  1. YouTube: Что такое Rest API, RESTful API / Back-end — Путь Самурая / Уроки по Back-end
  2. What Is a REST API?
  3. REST — Википедия