Что такое REST API? REST — это аббревиатура от Representational State Transfer — почти бессмысленное описание самой распространенной технологии веб-сервисов! REST API — это способ взаимодействия двух компьютерных систем с помощью технологий HTTP, используемых в веб-браузерах и серверах.
Обмен данными между двумя и более системами всегда был одним из основных требований при разработке программного обеспечения. Например, при покупке автостраховки. Страховщик должен получить информацию о Вас и Вашем автомобиле, поэтому он запрашивает данные у органов регистрации автомобилей, кредитных агентств, банков и других систем. Все это происходит прозрачно в режиме реального времени, чтобы определить, может ли страховщик предложить конкурентоспособный полис.
API (Application Programming Interfaces — интерфейсы прикладного программирования) способствуют такому взаимодействию между системами, предоставляя им интерфейс для общения друг с другом. REST — это просто широко распространенный стиль API, который мы используем для последовательного и предсказуемого взаимодействия с внутренними и внешними сторонами. Это можно сравнить с тем, как мы отправляем письмо с почтовой маркой, адресом и конвертом определенным образом, чтобы убедиться, что оно будет доставлено и прочитано.
REST широко используется людьми в веб-системах для взаимодействия друг с другом. Например, получение и обновление информации об учетной записи в приложении для социальных сетей.
Пример REST API
Это публичный API, реализованный как RESTful веб-сервис (он следует соглашениям REST). В браузере отображается один вопрос викторины в формате 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"]
}
]
}
Вы можете запросить тот же URL и получить ответ, используя любой HTTP-клиент, например curl:
curl "https://opentdb.com/api.php?amount=1&category=18"
Клиентские библиотеки HTTP доступны во всех популярных языках и средах исполнения, включая Fetch в JavaScript, Node.js и Deno и file_get_contents() в PHP. Ответ в формате JSON является машиночитаемым, поэтому его можно разобрать и использовать перед выводом в HTML или другие форматы.
REST API и остальное
В течение многих лет развивались различные стандарты передачи данных. Возможно, вам приходилось сталкиваться с такими вариантами, как CORBA, SOAP или XML-RPC. Большинство из них устанавливают строгие правила обмена сообщениями.
Вариант REST был определен в 2000 году Роем Филдингом и является значительно более простым, чем другие. Это не стандарт, а набор рекомендаций и ограничений для RESTful веб-сервисов. К ним относятся:
-
Клиент-сервер: СистемаА делает HTTP-запрос к URL-адресу, размещенному на сайте СистемыВ, которая возвращает ответ. Это идентично работе браузера. Браузер делает запрос на определенный URL. Запрос направляется на веб-сервер, который обычно возвращает HTML-страницу. Эта страница может содержать ссылки на изображения, таблицы стилей и JavaScript, что влечет за собой дополнительные запросы и ответы.
-
Другими словами, можно сделать два или более HTTP-запросов в любом порядке, и ответы будут одинаковыми (… если только API не рассчитан на случайные ответы, как в примере с викториной выше).
-
Кэшируемость: Ответ должен быть определен как кэшируемый или нет. Кэширование повышает производительность, поскольку нет необходимости заново генерировать ответ для одного и того же URL. Приватные данные, относящиеся к определенному пользователю в определенное время, обычно не кэшируются.
-
Уровневый: Запрашивающий клиент не должен знать, общается ли он с реальным сервером, прокси или любым другим посредником.
Создание RESTful Web-сервиса
RESTful веб-сервис запрос содержит:
-
Адрес конечной точки. Приложение, реализующее RESTful API, определяет одну или несколько конечных точек URL с указанием домена, порта, пути и/или строки запроса — например,
https://mydomain/user/123?format=json
. -
Метод HTTP. В любой конечной точке могут использоваться различные HTTP-методы, которые соответствуют операциям создания, чтения, обновления и удаления (CRUD), выполняемым приложением:
HTTP-метод | CRUD | Action |
---|---|---|
GET | read | возвращает запрошенные данные |
POST | create | создание новой записи |
PUT или PATCH | update | обновляет существующую запись |
DELETE | delete | удаляет существующую запись |
Примеры:
-
GET-запрос к
/user/
возвращает список зарегистрированных пользователей в системе -
POST-запрос к
/user/
создает пользователя с идентификатором123
, используя данные тела (см. 4. ниже). В ответ возвращается идентификатор. -
PUT-запрос к
/user/123
обновляет пользователя123
, используя основные данные (см. 4. ниже) -
GET-запрос к
/user/123
возвращает данные о пользователе123
. -
запрос DELETE к
/user/123
удаляет пользователя123
.
-
HTTP-заголовки. В заголовке HTTP-запроса может содержаться такая информация, как маркеры аутентификации или cookies.
-
Тело данных. Данные обычно передаются в теле HTTP-запроса аналогично HTML-представлениям
<form>
или путем отправки одной строки данных в кодировке JSON.
REST API Response
Полезная нагрузка ответа может быть любой: данные, HTML, изображение, аудиофайл и т. д. Обычно ответы на данные кодируются в JSON, но можно использовать XML, CSV, простые строки или любой другой формат. Можно разрешить указывать формат ответа в запросе — например, /user/123?format=json
или /user/123?format=xml
.
В заголовке ответа также должен быть задан соответствующий HTTP status code. Для успешных запросов используется 200 OK
, хотя при создании записи может быть возвращен и 201 Created
. Ошибки должны возвращать соответствующий код, например, 400 Bad Request
, 404 Not Found
, 401 Unauthorized
и т. д.
Могут быть установлены и другие HTTP-заголовки, включая директивы Cache-Control или Expires, определяющие, как долго ответ может кэшироваться, прежде чем он будет считаться устаревшим.
Однако строгих правил не существует. URL конечных точек, методы HTTP, тело данных и типы ответов могут быть реализованы как угодно. Например, POST
, PUT
и PATCH
часто используются как взаимозаменяемые, так что любой из них будет создавать или обновлять запись по мере необходимости.
Пример REST API «Hello World»
Следующий код Node.js создает RESTful веб-сервис с использованием фреймворка Express. Единственная конечная точка /hello/
отвечает на HTTP GET-запросы.
Убедитесь, что у вас установлен Node.js, затем создайте новую папку с именем restapi
. Создайте в этой папке новый файл package.json
со следующим содержимым:
{
"name": "restapi",
"version": "1.0.0",
"description": "REST-тест",
"scripts": {
"start": "node ./index.js"
},
"dependencies": {
"express": "4.18.1"
}
}
Запустите npm install
из командной строки для получения зависимостей, затем создайте файл index.js
со следующим кодом:
// простой Express.js RESTful API
'use strict';
// инициализация
const port = 8888,
express = require('express'),
app = express();
// /hello/ GET-запрос
app.get('/hello/:name?', (req, res) =>
res.json(
{ message: `Hello ${req.params.name || 'world'}!` }
)
);
// запускаем сервер
app.listen(port, () =>
console.log(`Сервер запущен на порту ${порт}`);
);
Запустите приложение из командной строки с помощью npm start
и откройте в браузере страницу http://localhost:8888/hello/
. В ответ на GET-запрос отображается следующий JSON:
{
"message": "Hello world!"
}
API также позволяет задать пользовательское имя, поэтому http://localhost:8888/hello/everyone/
возвращает:
{
"message": "Всем привет!"
}
REST-запросы на стороне клиента и CORS
Рассмотрим следующую HTML-страницу, запущенную в браузере по URL http://localhost:8888/
:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>REST-тест</title>
</head>
<body>
<script>
fetch('http://localhost:8888/hello/')
.then((response) => {
return response.json();
})
.then((json) => {
console.log(json);
});
</script>
</body>
</html>
Вызов fetch
выполняет тот же API-запрос, и в консоли браузера отображается Object { message: "Hello world!" }
, как и следовало ожидать.
Однако предположим, что ваш RESTful веб-сервис теперь размещен в Интернете на домене http://mydomain.com/hello/
. URL страницы JavaScript fetch()
изменился соответствующим образом, но при открытии страницы http://localhost:8888/
в браузере теперь выдается консольная ошибка Cross-Origin Request Blocked.
В целях безопасности браузеры разрешают только клиентские вызовы XMLHttpRequest и Fetch API на тот же домен, где размещена вызывающая страница.
К счастью, Cross-origin Resource Sharing (CORS) позволяет обойти это ограничение безопасности. Установка заголовка HTTP-ответа Access-Control-Allow-Origin
сообщает браузеру, что запрос разрешен. Он может быть задан для конкретного домена или *
для всех доменов (реализовано с помощью API Quiz, описанного выше).
Код API веб-сервиса может быть изменен таким образом, чтобы разрешить доступ с любого клиентского скрипта, работающего на любом домене:
// /hello/ GET-запрос
app.get('/hello/:name?', (req, res) =>
res
.append('Access-Control-Allow-Origin', '*')
.json({ message: `Hello ${req.params.name || 'world'}!` }),
);
В качестве альтернативы можно использовать промежуточную функцию Express.js, которая будет добавлять заголовок к каждому запросу конечной точки:
// включить CORS
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', '*');
next();
});
// /hello/ GET-запрос
Обратите внимание, что браузеры делают два запроса к REST API:
-
HTTP-запрос
OPTIONS
к тому же URL определяет, действителен ли заголовок HTTP-ответаAccess-Control-Allow-Origin
. -
Собственно REST-вызов
Когда ваш сервер получает метод запроса OPTIONS
, он может установить заголовок HTTP-ответа Access-Control-Allow-Origin
и вернуть фиктивный пустой ответ, чтобы исключить дублирование работы.
Вызовы REST API
Успех REST во многом объясняется его простотой. Разработчики могут реализовывать RESTful API по своему усмотрению, но это может привести к дополнительным проблемам. Для более детального рассмотрения стратегий реализации посмотрите нашу статью 13 лучших практик создания RESTful API.
Консенсус по конечным точкам
Рассмотрим следующие конечные точки:
-
/user/123
-
/user/id/123
-
/user/?id=123
Все они являются допустимыми вариантами получения данных для пользователя 123
. При выполнении более сложных операций количество комбинаций увеличивается. Например, верните десять пользователей, чьи фамилии начинаются с ‘A’ и которые работают в компанииX, начиная с записи 51, если упорядочить их по дате рождения в обратном хронологическом порядке.
В конечном счете, не имеет значения, как форматировать URL-адреса, но важна согласованность во всем API. Это может оказаться сложной задачей для больших кодовых баз с большим количеством разработчиков.
Версионирование REST API
Изменения в API неизбежны, но URL конечных точек никогда не должны быть недействительными, иначе это приведет к поломке использующих их приложений.
Чтобы избежать проблем совместимости, API часто версифицируются. Например, /2.0/user/123
заменяет /user/123
. При этом и новая, и старая конечная точка могут оставаться активными. К сожалению, в этом случае возникает необходимость поддерживать несколько исторических API. В конечном итоге старые версии могут быть отменены, но этот процесс требует тщательного планирования.
Аутентификация REST API
Приведенный выше API викторины является открытым: любая система может получить шутку без авторизации. Это не подходит для API, которые имеют доступ к частным данным или разрешают запросы на обновление и удаление.
Клиентские приложения, находящиеся в том же домене, что и RESTful API, будут отправлять и получать cookies так же, как и при любом другом HTTP-запросе. (Обратите внимание, что Fetch()
в старых браузерах требует установки параметра credentials
init option). Таким образом, запрос к API может быть проверен на предмет того, что пользователь вошел в систему и имеет соответствующие права.
Сторонние приложения должны использовать альтернативные методы авторизации. Общие опции аутентификации включают:
-
HTTP basic authentication. В заголовке запроса передается HTTP-заголовок
Authorization
, содержащий base64-кодированную строку имя пользователя: пароль. -
API-ключи. Стороннее приложение получает разрешение на использование API путем выдачи ключа, который может иметь определенные права или быть ограниченным определенным доменом. Ключ передается в каждом запросе в HTTP-заголовке или в строке запроса.
-
OAuth. Токен получается перед выполнением любого запроса путем отправки идентификатора клиента и, возможно, секрета клиента на OAuth-сервер. Затем токен OAuth отправляется с каждым запросом к API до истечения срока его действия.
-
JSON Web Tokens (JWT). Токены аутентификации с цифровой подписью надежно передаются как в заголовке запроса, так и в заголовке ответа. JWT позволяют серверу кодировать права доступа, поэтому обращение к базе данных или другой системе авторизации не требуется.
Аутентификация API зависит от контекста использования:
-
В некоторых случаях стороннее приложение рассматривается как любой другой вошедший в систему пользователь с определенными правами и разрешениями. Например, картографический API может возвращать вызывающему приложению информацию о маршрутах между двумя точками. Он должен подтвердить, что приложение является действительным клиентом, но не должен проверять учетные данные пользователя.
-
В других случаях стороннее приложение запрашивает данные, закрытые для отдельного пользователя, например содержимое электронной почты. REST API должен идентифицировать пользователя и его права, но ему может быть безразлично, какое приложение вызывает API.
Безопасность REST API
RESTful API предоставляет еще один путь для доступа и манипулирования вашим приложением. Даже если он не является громкой целью для взлома, плохо ведущий себя клиент может отправлять тысячи запросов каждую секунду и привести к краху вашего сервера.
Вопросы безопасности выходят за рамки данной статьи, но общие рекомендации включают:
-
использовать HTTPS
-
использовать надежный метод аутентификации
-
использовать CORS для ограничения обращений на стороне клиента к определенным доменам
-
обеспечивать минимальную функциональность — то есть не создавать опции DELETE, которые не требуются
-
проверять все URL-адреса конечных точек и данные тела
-
избегать раскрытия API-токенов в JavaScript на стороне клиента
-
блокировать доступ с неизвестных доменов или IP-адресов
-
блокировать неожиданно большие полезные нагрузки
-
учитывать ограничение скорости — т. е. количество запросов, использующих один и тот же API-токен или IP-адрес, не должно превышать N в минуту
-
отвечать соответствующим заголовком HTTP status code и caching
-
регистрировать запросы и расследовать отказы
Многочисленные запросы и ненужные данные
RESTful API ограничены своей реализацией. Ответ может содержать больше данных, чем нужно, или для доступа ко всем данным необходимо выполнить дополнительные запросы.
Рассмотрим RESTful API, предоставляющий доступ к данным об авторах и книгах. Чтобы показать данные о 10 самых продаваемых книгах, клиент может:
-
Запросить первые 10 книг
/book/
, упорядоченные по количеству продаж (первым идет самый продаваемый). Ответ содержит список книг с идентификатором каждого автора. -
Выполнить до 10 запросов
/author/{id}
для получения данных о каждом авторе.
Это известно как проблема N+1; для каждого результата в родительском запросе необходимо выполнить N запросов API.
Если это распространенный вариант использования, то RESTful API можно изменить таким образом, чтобы каждая возвращаемая книга содержала полную информацию об авторе: его имя, возраст, страну, биографию и т. д. Можно даже предоставлять полную информацию о других книгах автора — хотя это может значительно увеличить полезную нагрузку на ответ!
Чтобы избежать неоправданно больших ответов, можно настроить API таким образом, чтобы сведения об авторе были необязательными — например, ?author_details=full
. Количество опций, которые должны учитывать авторы API, может вызвать недоумение.
Исправляет ли GraphQL REST API?
Проблемы, связанные с REST, привели к тому, что компания Facebook создала GraphQL — язык запросов к веб-сервисам. Считайте, что это SQL для веб-сервисов: один запрос определяет, какие данные вам нужны и как вы хотите их получить.
GraphQL решает некоторые проблемы, возникающие при использовании RESTful API, но вводит и другие. Например, становится трудно кэшировать ответы на GraphQL.
Ваши клиенты вряд ли столкнутся с проблемами, сравнимыми с проблемами Facebook, поэтому, возможно, стоит рассмотреть возможность использования GraphQL после того, как RESTful API выйдет за свои практические рамки.
Ссылки на REST API и средства разработки
Существует множество инструментов для разработки RESTful API на всех языках. Среди них можно выделить следующие:
-
Swagger: разнообразные инструменты для разработки, документирования, моделирования, тестирования и мониторинга REST API.
-
Postman: приложение для тестирования REST-интерфейсов
-
Hoppscotch: веб-альтернатива Postman с открытым исходным кодом
Существует также множество публичных REST API, предназначенных для работы с анекдотами, конвертацией валют, геокодированием, государственными данными и всеми другими темами, которые только можно придумать. Многие из них бесплатны, хотя некоторые требуют регистрации ключа API или использования других методов аутентификации. Списки по категориям включают:
Попробуйте использовать некоторые RESTful API в своих проектах, прежде чем реализовывать собственные веб-сервисы. Или же можно пойти по стопам Facebook, GitHub, Google и многих других гигантов, создав собственный RESTful API.
FAQs About REST API
Что такое REST API?
REST API (Representational State Transfer Application Programming Interface) — это набор правил и соглашений, позволяющих программным приложениям общаться и взаимодействовать друг с другом через Интернет, используя принципы архитектурного стиля REST.
Каковы основные характеристики REST API?
Для REST API характерно использование ресурсов, безэталонное взаимодействие клиент-сервер, стандартные методы HTTP (GET, POST, PUT, DELETE) и унифицированные интерфейсы, которые обычно предполагают использование URL-адресов для доступа к ресурсам и работы с ними.
Почему API называется REST?
REST API (Representational State Transfer Application Programming Interface) назван в честь архитектурного стиля, которому он следует, известного как REST (Representational State Transfer). Термин «REST» был введен Роем Филдингом в его докторской диссертации 2000 года, где он изложил принципы и ограничения этого архитектурного стиля. Название «REST» означает концепцию передачи представления состояния ресурса от сервера к клиенту.
Каковы преимущества использования REST API?
REST API обладают рядом преимуществ, включая простоту, масштабируемость, легкость интеграции, независимость от платформы и разделение проблем. Кроме того, они используют существующую инфраструктуру HTTP и хорошо подходят для веб- и мобильных приложений.
Ограничиваются ли REST API только веб-приложениями?
Нет, REST API не ограничиваются веб-приложениями. Они могут использоваться для обеспечения взаимодействия между различными типами программных приложений, включая веб-приложения, мобильные приложения и даже межсерверные коммуникации.
Каковы четыре компонента REST API?
REST API состоит из четырех основных компонентов, которые часто называют «четырьмя столпами» REST. Эти компоненты помогают определить структуру, поведение и взаимодействие API в рамках архитектурного стиля REST. Этими четырьмя компонентами являются ресурсы, HTTP-методы (глаголы), представления и универсальный интерфейс.
Какие инструменты или библиотеки можно использовать для создания REST API?
Для создания REST API существует несколько инструментов и фреймворков, в том числе Express.js (Node.js), Flask (Python), Ruby on Rails (Ruby), Django (Python), Spring Boot (Java) и другие.