Первый модуль закончился тем, что вы создали HTTP-запрос, отправили его и получили ответ.

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

Поэтому хорошо бы тщательно изучить все, что связано с этими запросами, детально проанализировать их. Чтобы не просто скопировать запрос куда-то и повторить его, а действительно разобраться, как это все работает.

Именно этим мы и займемся во втором модуле. Поехали!

Начнем с теории.


Изучение REST API

Основы REST API

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

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

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

REST - аббревиатура от Representational State Transfer. Возможно, это звучит не очень понятно, но если говорить просто, то REST - это стиль взаимодействия (обмена информацией) между клиентом и сервером.

Это не какой-то жесткий набор правил и требований. REST не заставляет использовать какой-то конкретный язык программирования и не связывает руки строгими рекомендациями. REST называют архитектурным стилем, и он определяет 6 принципов, которым должна соответствовать архитектура системы.

Соответственно, API, разработанный с учетом принципов REST, называется REST API, а сами приложения - RESTful.

Мы будем создавать именно такие RESTful-приложения, поэтому сразу стоит обсудить принципы, которым они будут соответствовать.

  1. Модель клиент-сервер. Этот принцип определяет разделение клиента и сервера, разграничение их потребностей. Клиенту не нужно заботиться о том, как хранятся данные, главное, чтобы они выдавались по запросу. В свою очередь, серверу все равно, что клиент будет делать с этими данными, как их дальше обрабатывать и отображать. Это позволяет им развиваться независимо друг от друга и улучшает масштабируемость системы.
  2. Нестационарность. Этот принцип означает, что сервер не должен "придумывать" ответ, основываясь на предыдущем опыте работы с данным клиентом. Любой запрос делается таким образом, чтобы он содержал всю необходимую для его обработки информацию, независимо от предыдущих запросов.
  3. Кэширование. Для минимизации передаваемых данных существует механизм кэширования. Например, если на какой-то странице отображается логотип, то нет смысла каждый раз запрашивать его у сервера. Он меняется не так часто, достаточно будет получить его один раз и сохранить на компьютере клиента, в кэше. Но если нам нужно получить информацию о текущей скорости автомобиля, то кэш ничем не поможет. Этот принцип определяет, что данные, передаваемые сервером, должны быть обозначены как кэшируемые или нет.
  4. Единообразный интерфейс. Этот принцип определяет единый формат взаимодействия клиента и сервера. Структура всех запросов должна быть одинаковой. Данные должны передаваться в одинаковой форме, независимо от того, кто их запрашивает.
  5. Многоуровневая система. Клиент и сервер не обязательно взаимодействуют напрямую. Передача данных может проходить через несколько промежуточных узлов. В этом случае система строится таким образом, чтобы ни клиент, ни сервер не знали, взаимодействуют ли они с конечным приложением или с промежуточным узлом. Это позволяет сбалансировать нагрузку на серверы, повысить масштабируемость.
  6. Код по требованию (необязательный). Единственный принцип, который не является обязательным. Согласно ему, клиент может расширять свою функциональность, загружая исполняемый код с сервера (например, скрипты). В этом случае код должен выполняться только по требованию.

Не слишком много теории?

Давайте применим это на практике.

Создание API-запроса

Давайте откроем AppMaster, создадим с его помощью API-запрос и лучше поймем, как этот запрос работает.


API-запросы создаются в разделе "Бизнес-логика", во вкладке "Внешние API-запросы".

Пришло время нажать "+ Новый API-запрос".


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

Давайте разберемся с данными, которые действительно важны.

Минимум, что требуется для создания запроса, - это указать его Метод и адрес (URL). Начнем с последнего.


URL - Uniform Resource Locator (унифицированный указатель ресурса). Адрес, присваиваемый определенному ресурсу в Интернете. Наиболее привычным вариантом такого ресурса является HTML-страница - мы вводим ее URL в адресную строку браузера и открываем нужный сайт. В то же время сам ресурс может быть чем угодно - картинкой, видео, набором данных. Главное, чтобы у этого ресурса был определенный указатель - URL, на который можно послать запрос, чтобы получить этот ресурс.

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

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

Давайте посмотрим, какие еще методы существуют.


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

  • GET. С ним уже разобрались. Метод запрашивает предоставление ресурса и получает данные.
  • POST. Чтобы взять данные откуда-то, сначала нужно эти данные туда поместить. Метод POST делает именно это. Отправляет данные на сервер, создает ресурс.
  • PUT. Аналогичен методу POST, но его задача - обновить данные. Он не создает новые данные, а заменяет существующие, обновляет их.
  • DELETE. Как следует из названия, удаляет данные.
  • PATCH. Этот метод похож на PUT, но используется для частичного обновления данных, а не для полной замены. Например, используя метод PATCH, вы можете изменить заголовок статьи или изменить значение какого-либо параметра.

Важно учитывать тот факт, что сервер вовсе не обязан делать именно то, что указано в методе. Мы можем передать адрес какой-то страницы с помощью метода DELETE, но это не значит, что сервер действительно удалит ее. Но, чисто теоретически, он может сделать это с помощью команды GET. Или ничего не менять, но при этом отправлять данные в ответ на POST. Просто потому, что разработчик так настроил.

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

Итак, мы разобрались, где находятся данные и что с ними можно сделать. Пойдем дальше, посмотрим, какие еще компоненты может иметь запрос.


Параметры URL. Бывают ситуации, когда мы знаем только часть URL. Примером могут служить статьи на сайте Appmaster.io. Начальный адрес для всех статей один и тот же - https://appmaster.io/en/blog/. Но затем каждая статья имеет свой заголовок и, соответственно, свою индивидуальную часть для точного указания именно этой статьи.

В такой ситуации используются URL Params. Мы сразу прописываем общую часть, а остальное оставляем решать в процессе. В результате URL записывается в виде https://appmaster.io/ru/blog/:id/.

Известная часть записывается как есть, а переменная часть помещается после знака ":". Имя этой переменной части (уже без ":") добавляется к списку параметров. В данном случае переменных частей может быть несколько, и их расположение может быть любым в URL.


Параметры запроса. Помните, как в первом модуле мы отправляли запрос на boredapi.com? И помимо адреса были прописаны дополнительные данные. Это были параметры запроса (Query Params).

Они прописываются после URL и отделяются от него знаком "?". Указывается имя параметра, знак "=" и значение самого параметра. Если используется сразу несколько параметров, они разделяются знаком "&".

Однако при указании параметров в AppMaster не нужно думать о правилах запроса. Все будет правильно отформатировано автоматически. Вам просто нужно указать имя самого параметра и добавить его в список.

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

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

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

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

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

Тело. Тело запроса. GET-запросы обычно обходятся без него, но если мы хотим отправить какие-то данные на сервер, посылаем POST или PUT запрос, то эти данные помещаются в тело запроса. При этом в тело запроса можно поместить данные любой сложности, например, отправить видеофайл, и не ограничиваться каким-то числом или текстовой строкой.

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

Важным отличием является статус ответа.

Код статуса. Он указывается в первой строке ответа сервера. Статус представляет собой трехзначное число (сам код), за которым следует фраза, поясняющая его.

Именно по коду статуса можно узнать о результатах запроса и понять, какие действия следует предпринять дальше.

Все возможные коды статуса делятся на 5 классов. Первая цифра кода определяет принадлежность к тому или иному классу. Давайте разделим их на классы.

1xx - информационные коды. Сообщают о ходе выполнения запроса. В реальной практике используются редко.

2xx - коды успеха. Они сообщают, что все в порядке и запрос был успешно завершен. В ответ на запрос GET мы обычно ожидаем получить код 200 (OK). Успешный запрос PUT посылает код 201 (Created).

3xx - перенаправления. Указывают на то, что запрос должен быть отправлен на другой адрес. Примером может служить код 301 (Moved Permanently), указывающий на то, что требуемые данные теперь находятся по новому адресу (сам новый адрес передается в заголовке Location).

4xx - коды ошибок клиента. Самый известный из них - 404 (Not Found), сообщает, что по указанному адресу нет необходимых данных. Другие распространенные случаи: 400 (Bad Request, синтаксическая ошибка в запросе), 401 (Unauthorized, для доступа требуется аутентификация), 403 (Forbidden, доступ запрещен).

5xx - коды ошибок сервера. Сообщают об ошибке на стороне сервера. Например: 500 (Internal Server Error, любая непонятная ошибка, которую нельзя отнести к известному коду), 503 (Service Unavailable, сервер временно не может обработать запрос по техническим причинам).

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


Обычно человеку довольно очевидно, как работать с этими данными, поскольку есть определенный контекст. Предположим, мы знаем, что 2 + 2 = 4. Мы догадываемся, что это числа и результатом сложения будет другое число.

Но это могут быть не числа, а текстовые данные. Тогда результатом их сложения может быть конкатенация строк, и 2 + 2 превратится в "22". Здесь, чтобы компьютеру не пришлось ничего придумывать, есть точное указание типа данных. И в то же время решаются другие задачи. Например, обеспечивается защита от ввода неверных данных; изначально нет возможности зарегистрировать адрес электронной почты в поле, предназначенном для ввода цифр телефонного номера.

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

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

Integer - Целочисленный тип данных. Может использоваться для счетчиков или вычислений, где дробные числа не нужны.

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

Здесь может возникнуть логичный вопрос. А почему бы не использовать всегда Float, зачем тогда нужны Integer? Но большая точность требует больше ресурсов. Для некоторых небольших вычислений это может быть совершенно незаметно, но в случае больших объемов данных использование разумного типа данных может значительно снизить требования к вычислительной мощности и дисковому пространству.

Boolean - булев тип данных. Самый простой тип данных. Он принимает одно из двух значений, которые записываются как True или False. Часто можно встретить обозначение в виде 1 (true) и 0 (false).


Домашнее задание

Повторите запросы из домашнего задания к первому модулю, создав их в AppMaster в разделе External API Requests.

  1. Создайте запрос к BoredAPI. Укажите не менее 5 различных параметров из документации. Отправьте несколько разных запросов, указывая только необходимые параметры.
  2. Создайте запрос к Alphavantage. Используйте параметры для получения курсов различных валют по отношению друг к другу.