Что такое REST API?

0 5

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

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

REST повсеместно используется в веб-системах для взаимодействия. Например, получение и обновление данных профиля в социальной сети.

Пример REST API

Перейдите по следующий ссылке, в ответ вы получите случайный вопрос по компьютерам с портала Open Trivia Database.

Что такое REST API?

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Это публичный API, реализованный как RESTful веб-сервис (следует правилам REST). В браузере отобразится один вопрос с ответом в формате JSON, как на примере ниже:

JavaScript { «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» ] } ] }

1234567891011121314151617 {  «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»      ]    }  ]}

Вы можете выполнить этот запрос и получить ответ в любом HTTP-клиенте, например curl:

JavaScript curl «https://opentdb.com/api.php?amount=1&category=18»

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

Библиотеки HTTP-клиентов доступны на всех популярных языках программирования и рантаймах, в том числе Fetch для JS, Node.js и Deno, а также file_get_contents() для PHP. JSON ответ машиночитаемый, т.е. его можно распарсить перед выводом в HTML или другой формат.

REST API и Rest

За последние годы развилось множество стандартов передачи данных. Вы могли слышать про CORBA, SOAP или XML-RPC. Большинство стандартов устанавливают строгие правила передачи сообщений.

REST придумал Roy Fielding в 2000 году. Его подход значительно проще остальных. Это не стандарт, а набор рекомендаций и ограничений для RESTful сервисов. Выделяют следующие правила:

Клиент-сервер: система А делает HTTP запрос на URL, по которому развернута система B. Система B отвечает. Принцип идентичен работе браузера. Браузер посылает запрос по URL. Запрос направляется на веб-сервер, который обычно отвечает HTML-страницей. Страница может содержать ссылки на изображения, стили и JS. Все это ведет к последующим запросам и ответам.

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

Кэшируемость: респонс должен помечаться как кэшируемый или нет. Кэширование улучшает производительность, позволяя не генерировать повторно ответ на такой же URL. Однако приватные данные пользователей в определенные моменты лучше не кэшировать.

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

Создание RESTful веб-сервиса

Запрос RESTful сервиса содержит:

Эндпоинт URL. Приложение, реализующее RESTful API, определяет один или более URL эндпоинтов с доменом, портом, самим эндпоинтом и/или строкой параметров. Например, https://mydomain/user/123?format=json

HTTP метод. Любой эндпоинт может использовать различные HTTP методы, которые ведут в приложении к операциям создания, чтения, обновления и удаления данных (CRUD):

Что такое REST API?

Примеры:

GET запрос к /user/ вернет список зарегистрированных пользователей в системе

POST запрос к /user/ создаст нового юзера с ID 123 на основе переданных данных (см пункт 4 далее). В ответ мы получим ID

PUT запрос к /user/123 обновит юзера 123 данными, которые мы передали (см пункт 4 далее)

GET запрос к /user/123 вернет информацию по юзеру 123

DELETE запрос к /user/123 удалит юзера 123

Также запрос RESTful сервиса содержит:

HTTP заголовки. Информация типа токенов авторизации или куки может храниться в HTTP заголовках запроса.

Тело запроса. Данные обычно передаются в HTTP теле аналогично передаче данных через HTML form или передаче данных через JSON.

Что такое REST API?

REST API ответ

Ответ может содержать все что угодно: данные, HTML, изображений, аудио файл итд. Обычно ответ кодируют в JSON, но бывают ответы в XML, CSV, в виде простых строк итд. Возвращаемый формат можно указать в самом запросе. Например, /user/123?format=json или /user/123?format=xml.

В хедерах ответа также необходимо указать подходящий HTTP статус код. 200 OK используется для успешных запросов, 201 Created можно вернуть при создании записи. У ошибок свои коды, например, 400 Bad Request, 404 Not Found, 401 Unauthorized и так далее.

Другие хедеры можно указать через директивы Cache-Control или Expires. С их помощью можно указать время кэширования.

Тем не менее, нет строгих правил. Эндпоинты, HTTP методы, тело и типы ответов можно реализовывать по-своему. Например, POST, PUT и PATCH часто используют так, что они становятся взаимозаменяемыми и через любой из них можно создать или обновить запись.

Пример Hello World REST API

Node.js код ниже создает RESTful сервис на фреймворке Express. У этого приложения есть один эндпоинт GET /hello/. Установите Node.js, создайте папку restapi. Внутри папки создайте package.json:

JavaScript { «name»: «restapi», «version»: «1.0.0», «description»: «REST test», «scripts»: { «start»: «node ./index.js» }, «dependencies»: { «express»: «4.18.1» } }

1234567891011 {  «name»: «restapi»,  «version»: «1.0.0»,  «description»: «REST test»,  «scripts»: {    «start»: «node ./index.js»  },  «dependencies»: {    «express»: «4.18.1»  }}

Выполните команду npm install в командной строке, чтобы загрузить зависимости. Далее создайте файл index.js:

JavaScript // simple Express.js RESTful API ‘use strict’; // initialize const port = 8888, express = require(‘express’), app = express(); // /hello/ GET request app.get(‘/hello/:name?’, (req, res) => res.json( { message: `Hello ${req.params.name || ‘world’}!` } ) ); // start server app.listen(port, () => console.log(`Server started on port ${port}`); );

1234567891011121314151617181920 // simple Express.js RESTful API’use strict’; // initializeconst  port = 8888,  express = require(‘express’),  app = express(); // /hello/ GET requestapp.get(‘/hello/:name?’, (req, res) =>  res.json(    { message: `Hello ${req.params.name || ‘world’}!` }  )); // start serverapp.listen(port, () =>  console.log(`Server started on port ${port}`););

Запустите приложение через командную строку npm start. Откройте в браузере http://localhost:8888/hello/. На экране отобразится JSON:

JavaScript { «message»: «Hello world!» }

123 {  «message»: «Hello world!»}

API позволяет передавать имя. То есть запрос на http://localhost:8888/hello/everyone вернет:

JavaScript { «message»: «Hello everyone!» }

123 {  «message»: «Hello everyone!»}

Клиентские REST запросы и CORS

Рассмотрим HTML-страницу ниже, запущенную в браузере по URL http://localhost:8888:

<!DOCTYPE html> <html lang=»en»> <head> <meta charset=»UTF-8″> <title>REST test</title> </head> <body> <script> fetch(‘http://localhost:8888/hello/’) .then((response) => { return response.json(); }) .then((json) => { console.log(json); }); </script> </body> </html>

123456789101112131415161718 <!DOCTYPE html><html lang=»en»><head><meta charset=»UTF-8″><title>REST test</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 для fetch изменился. Но если открыть http://localhost:8888 в браузере, мы получим ошибку в консоли Cross-Origin Request Blocked.

По соображениям безопасности браузеры разрешают клиентам выполнять XMLHttpRequest и Fetch API запросы только на тот же домен, откуда идет сам запрос.

К счастью, Cross-origin Resource Sharing (CORS) позволяет нам обойти это ограничение. Заголовок ответа Access-Control-Allow-Origin скажет браузеру, куда он может посылать запросы. В значении можно указать конкретный домен или * для любого домена (как сделано в API из примера выше).

Код API можно изменить, чтобы сервис мог отвечать любому клиенту на любом домене:

JavaScript // /hello/ GET request app.get(‘/hello/:name?’, (req, res) => res .append(‘Access-Control-Allow-Origin’, ‘*’) .json( { message: `Hello ${req.params.name || ‘world’}!` } ) );

12345678 // /hello/ GET requestapp.get(‘/hello/:name?’, (req, res) =>  res    .append(‘Access-Control-Allow-Origin’, ‘*’)    .json(      { message: `Hello ${req.params.name || ‘world’}!` }    ));

Или можно через Express.js middleware функцию добавить наш хедер во все запросы:

Что такое REST API?

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

JavaScript // enable CORS app.use((req, res, next) => { res.append(‘Access-Control-Allow-Origin’, ‘*’); next(); }); // /hello/ GET request // …

12345678 // enable CORSapp.use((req, res, next) => {  res.append(‘Access-Control-Allow-Origin’, ‘*’);  next();}); // /hello/ GET request// …

Обратите внимание, что браузеры делают два запроса к REST API:

Запрос OPTIONS на тот же адрес, чтобы определить правильность хедера Access-Control-Allow-Origin

Сам REST запрос

Чтобы не дублировать код на запрос OPTIONS можно возвращать хедер Access-Control-Allow-Origin с пустым ответом.

Сложности в REST API

Успех REST в его простоте. Разработчики сами пишут RESTful API, как хочется им. Однако это может привести к некоторым сложностям. Для углубленного изучения стратегий архитектуры API ознакомьтесь с нашим уроком «13 лучших практик по созданию RESTful API».

Консенсус по эндпоинтам

Разберем следующие эндпоинты:

/user/123

/user/id/123

/user/?id=123

Все варианты подходят для получения данных для юзера 123. Количество комбинаций будет расти вместе со сложностью операций. Например, вернуть 10 юзеров, чьи фамилии начинаются на А, и кто работает на компанию Х, начиная с записи 51 с сортировкой по дате рождения в обратном от хронологического порядке.

Абсолютно неважно, как вы будете форматировать URL, однако консистентность во всем API очень важна. В большом проекте, где много разработчиков, это может вызвать некоторые сложности.

Версирование REST API

Изменения в API неминуемы, но нельзя ломать существующие URL. Иначе это приведет к поломке приложения.

Чтобы избежать проблем совместимости, API зачастую устанавливают версию. Например, /2.0/user/123 заменяет /user/123. Оба эндпоинта могут оставаться активными. Такой подход заставляет поддерживать несколько версий API. В будущем старые версии можно удалить, но этот процесс нужно тщательно спланировать.

REST API аутентификация

API из примера в начале статьи открытый: любая система может получить от него шутку без авторизации. Для API с доступом к приватным данным с возможностью обновлять и удалять эти данные такой подход не применим.

Клиентские приложения в том же домене что и RESTful API будут отправлять и получать куки, как любой другой HTTP запрос. (обратите внимание, что Fetch() в старых браузерах требует credentials init опцию) API запрос можно провалидировать на авторизацию юзера и на наличие подходящих прав пользователя.

Сторонние приложения должны использовать альтернативные способы авторизации. Среди часто используемых способов аутентификации выделяют:

HTTP basic аутентификацию. HTTP заголовок Authorization со строкой username:password, закодированной в base64.

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

OAuth. Перед работой с API требуется получить токен. Для этого отправляется запрос с ID клиента и возможно с секретным ключем на OAuth сервер. Далее токен отправляется в каждом API запросе до тех пор, пока он не прекратит действие.

JSON веб токены (JWT). Токены аутентификации подписаны цифровой подписью и безопасно передаются в хедерах запроса и ответа. JWT позволяет серверу кодировать права доступа, из-за этого не требуются дополнительные обращения в базу данных или системы авторизации.

API аутентификация выбирается исходя из контекста:

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

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

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

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

Безопасность выходит за рамки нашей статьи, но можно перечислить общепринятые лучшие практики:

Используйте HTTPS

Используйте надежный метод аутентификации

Ограничивайте количество клиентских запросов к определенным доменам через CORS

Предоставляйте минимум функциональности – не создавайте DELETE метод, если он не нужен

Валидируйте все эндпоинты и тело запросов

Не храните API токены в клиентском JS

Блокируйте доступ с неизвестных доменов и ip-адресов

Блокируйте неожиданно большие нагрузки

Подумайте о лимите на запросы – ограничить запросы под одним API токеном или IP до N количества в минуту

Отвечайте подходящими статус кодами и кэшируйте хедеры

Логируйте запросы и исследуйте проблемы

Множественные запросы и ненужные данные

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

Рассмотрим RESTful API, предоставляющим доступ к данным автора и его книг. Для получения данных о топ-10 продаваемых книг клиент может:

Запросить первые 10 /book/ отсортированные по количеству продаж (самая продаваемая сверху). В ответе может содержаться список книг с ID авторов.

Выполнить 10 запросов /author/{id} для получения данных по каждому автору.

Это известная проблема, ее называют проблемой N+1. Для родительского запроса нужно выполнить N API запросов для каждого результата.

Если это распространенный пример, то RESTful API можно изменить таким образом, чтобы в каждой возвращаемой книге была вся информация по автору: имя, возраст, страна, биография итд. В ответе даже может храниться информация по его другим книгам – но это увеличит респонс!

Без необходимости не раздувайте респонсы. API можно настроить так, чтобы детали по автору были необязательным параметром. Например, ?author_details=full. Количество опций, которые нужно учесть автору API, может сбить с толку.

GraphQL фиксит REST API?

Сложные задачки с REST навели на мысль создать GraphQL – язык запросов веб-сервисов. Представьте, что это SQL для веб-сервисов: строка запроса определяет возвращаемые данные и их формат.

GraphQL решает некоторые проблемы RESTful APIs, но и вносит новые сложности. Например, сложнее кэшировать GraphQL респонсы.

Возможно, стоит подумать о GraphQL, когда ваш RESTful API выходит за пределы своего практического применения.

Ссылки по REST API и инструмент для разработки

Существует множество инструментов для разработки RESTful API на всех языках. Выделить можно:

Swagger: различные инструменты для проектирования, документирования, написания заглушек и мониторинга REST API

Postman: приложение для тестирования RESTful API

Hoppscotch: open-source веб альтернатива Postman

Также есть много публичных REST API для генерации шуток, конвертации валют, геокодирования, получения гос. данных и еще много всего, что сложно представить. Множество из них бесплатны, часть требует авторизации для получения API ключа или для авторизации через другие методы. Списки по категориям:

Any API

API list

Public API

Google API Explorer

Перед написанием своего веб-сервиса попробуйте использовать парочку RESTful API в своем проекте. Или последуйте примеру GitHub, Google и других гигантов индустрии и постройте свой RESTful API.

Автор: Craig Buckler

Источник: webformyself.com

Оставьте ответ

Ваш электронный адрес не будет опубликован.