Введение в API и REST API

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

В этой статье мы разберемся в том, что такое API, как оно работает, какие дает преимущества и каких типов бывает. Подробнее остановимся на REST API, рассмотрим его возможности, а также, конечно же, попрактикуемся в вызове HTTP-запросов на примере 1cloud API.

Что такое API?

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

Чаще всего вы встретите определение API как Application Programming Interface — программный интерфейс приложения. Приложением может быть любое ПО или программа, которая что-то принимает на вход для обработки данных и что-то возвращает после обработки. Такая схема очень похожа на взаимодействие логико-структурных элементов ЯП: классы, методы, функции, переменные.

Например, в Python, это может выглядеть так:

from functools import reduce

def quader(*args: int) -> int:
    """
    Функция принимает на вход любое количество аргументов, перемножает их между собой, возводит в квадрат и возвращает результат в виде целочисленного числа.
    """
    return reduce(lambda x, y: x * y, map(lambda x: x * x, args))

def fibonachi(n: int) -> list:
    """
    Функция принимает на вход целочисленное число и строит ряд Фибоначчи, длиной равной переданному аргументу в функцию.
    """
    fib_sequence = [0, 1]
    for i in range(2, n):
        fib_sequence.append(fib_sequence[-1] + fib_sequence[-2])
    return fib_sequence[:n]

print(fibonachi(quader(2,2)))

Как видно из примера мы создали две функции, а затем передали одну функцию в качестве аргумента другой функции и распечатали результат. Такое возможно благодаря внутреннему API Python. Обычно API реализует клиент-серверную модель. Это когда есть программа, которая располагается где-то на VPS/сервере/облаке, а к ней подключаются клиенты и она возвращает им какие-то данные в зависимости от их запроса. По такой схеме работают многие мобильные приложения, сайты и БД.

Например, подключение к СУБД SQL и работа с ней происходит по-стандартизированному API, который определяет SQL-команды и данные, которые будут возвращены. Другой интересный пример работы API — это Google- и Yandex-карты, которые используются в их сервисах. К примеру, приложение Yandex GO (Такси) использует сразу множество API:

  • для определения местоположения используется API андроида для запроса к GPS;
  • для отображения карты используется API Yandex Карт;
  • для оплаты используется API эквайринга.

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

Благодаря такому подходу разработчики и пользователи получили удобные инструменты разработки и взаимодействия с целыми системами. Например, ОС предоставляет API для работы программ с ресурсами компьютера. Так программы могут получать доступ к видеокарте для отрисовки графики, или получать доступ к устройствам ввода для взаимодействия с интерфейсом программы.

Как мы говорили ранее, API определяет не только какая информация и в каком формате будет передана, но и как эту информацию нужно передать. Всего есть 4 общепринятых типа построения API:

  1. SOAP (Simple Object Access Protocol) — это протокол для обмена структурированными сообщениями между веб-сервисами. Он использует формат данных XML для кодирования сообщений. SOAP применяется в распределенных системах и веб-сервисах для взаимодействия между клиентами и серверами. Сегодня SOAP встречается не так часто, так как XML довольно громоздкий, а сама архитектура SOAP не гибкая.
  2. RPC (Remote Procedure Call) API — это метод взаимодействия между компонентами распределенной системы, позволяющий вызывать функции на удаленном сервере, как будто они являются локальными. Формат данных в RPC может быть разным, включая XML, JSON и бинарные форматы. RPC API применяется в распределенных системах для обеспечения совместной работы между клиентами и серверами с минимальными задержками.
  3. WebSocket API — это двунаправленный протокол связи, позволяющий установить постоянное соединение между клиентом и сервером для обмена данными в режиме реального времени. Формат данных в WebSocket может быть текстовым или бинарным, включая JSON, XML и другие. WebSocket API часто используется в веб-приложениях для обмена сообщениями между сервером и браузером пользователя, например, в онлайн-играх, чатах или приложениях для обмена данными в реальном времени.
  4. REST (Representational State Transfer) API — это архитектурный стиль для разработки веб-сервисов, основанный на стандартных HTTP-методах и ресурсоориентированном подходе. Формат данных в REST API может быть разнообразным, включая JSON, XML и другие. REST API широко применяется в веб-приложениях и мобильных приложениях для обеспечения межсистемного взаимодействия и интеграции с различными сервисами и платформами.

Наибольшее распространение получил REST формат API, так как он наиболее прост для разработки и понятен для пользователей. Именно о REST мы и будем говорить далее.

Что такое REST API?

REST (Representational State Transfer) API работает поверх HTTP(S)-протокола и максимально эффективно использует его свойства. Можно сказать, что REST — это не какой-то стандарт, а архитектурный стиль написания запросов. Часто ещё его называют RESTful API. А вот HTTP (HyperText Transfer Protocol) — это протокол передачи данных, используемый во всемирной паутине для обмена информацией между клиентами и серверами.

HTTP определяет методы запроса к ресурсу, которые используются для выполнения разных операций:

  1. GET-запрос используется для получения информации от сервера. Он запрашивает данные от определенного ресурса и не вносит изменения на сервере. Примером может быть просмотр веб-страницы или получение данных из API.
  2. PUT-запрос используется для обновления существующих данных на сервере. Он требует передачи полного обновленного набора данных для указанного ресурса. Если ресурс не существует, сервер может создать его, в зависимости от реализации.
  3. DELETE-запрос используется для удаления указанного ресурса на сервере. Он не требует передачи дополнительных данных.
  4. POST-запрос используется для создания нового ресурса на сервере. Он передает данные, которые должны быть использованы для создания нового ресурса. В отличие от PUT-запроса, POST-запрос не требует знания о существующих ресурсах и их идентификаторах.

HTTP-запрос определяется HTTP-методом и может содержать различные заголовки и информацию в виде JSON-данных для обработки. Вот так может выглядеть схема работы HTTP-запроса к 1cloud API для получения баланса проекта:

Как видно из схемы клиент отправляет запрос на определенный URI, с указанием конкретного метода запроса и заголовками. В нашем случае, мы послали GET-запрос на URI: https://api.1cloud.ru/customer/balance с заголовком Authorization и значением Bearer … — многоточие указывает на API-ключ, который обязательно указывается при любых API-запросах к 1cloud API.

В ответ API-сервер 1cloud нам возвращает список значений. Об этом свидетельствуют квадратные скобки. В зависимости от запроса, API-сервер может возвращать различной сложности JSON-данные. Например, при запросе списка серверов, в ответ мы получим JSON следующего вида:

[
{
  "ID":777,
  "Name":"test2API",
  ...
  "LinkedNetworks": [
            {
                "LinkID": 139856,
                "NetworkID": 274,
                ..
            },
            {
                "LinkID": 154883,
                "NetworkID": 1362,
                ..
            }
        ],
  "DCLocation":"SdnSpb",
  "ImageFamily":"Windows",
  "LinkedSshKeys": []
 }
 ...
 ]

JSON является общепринятым форматом передачи данных в REST API, так как его легко конвертировать в любой другой формат и с ним работают все ЯП.

Еще одной важной отличительной чертой REST является то, что REST API не хранят состояния. Это означает, что при каждом обращении к ресурсу через определенную конечную точку (endpoint), API предоставляет идентичный ответ, не учитывая предыдущие запросы, которые не влияют на последующие результаты.

Хорошо, у нас уже есть общее представление о том, что такое API и REST API. Настало время углубиться и разобраться детальнее в том, как оно работает.

Работа REST API на примере 1cloud API

Рассмотрим работу REST API на примере реализации 1cloud API. Как мы уже говорили ранее, одно из ключевых понятий REST API — это ресурс. Ресурсы связаны с определенными URI, а те в свою очередь связаны с HTTP-методами запроса.

1cloud — это облачный провайдер, который предоставляет такие ресурсы как виртуальные серверы на базе Enterprise и Open Source виртуализаций, виртуальные ЦОДЫ, S3-хранилища, DNS-хостинг, мониторинг и многие другие услуги, некоторые из которых имеют управление по API. Например, виртуальные серверы.

Для управления виртуальными серверами 1cloud нужно посылать определенные HTTP-запросы на нужные URL. Структура URL и запросов следующая:

URL HTTP-запрос Действие Ответ
https://api.1cloud.ru/server/ GET Запросить список созданных серверов. JSON со списком созданных серверов.
POST Создать виртуальный сервер. JSON со статусом создания виртуального сервера.
https://api.1cloud.ru/server/{id} DELETE Удаление виртуального сервера по id. Текст со статусом «OK».
PUT Изменение конфигурации виртуального сервера по id. JSON со статусом задачи и выходными параметрами измененного сервера.
https://api.1cloud.ru/server/{id}/action POST Выполнение действий над сервером: вкл./выкл. сервер по питанию и средствами OS, перезагрузить сервер по питанию или средствами OS. JSON со статусом задачи.
https://api.1cloud.ru/server/{id}/action GET Получить список действий над сервером. JSON со списком действий над сервером.

Использование HTTP-методов, как правило, подразумевает передачу дополнительных заголовков и данных для обработки на сервере. В случае с 1cloud API в качестве дополнительного заголовка передается:

  • Тип данных, которые отправляются или принимаются от сервера — Content-Type: application/json;
  • API-ключ для авторизации — Authorization: Bearer XXX…

В теле сообщения, в JSON-формате передаются данные необходимые для выполнения определенных действий. Так заголовок авторизации с API-ключем передается всегда: 'Authorization: Bearer XXX..', а вот данные в теле запроса, указываются только для PUT и POST запросов.

Получить API-ключ для авторизации можно в Панели управления 1cloud, в разделе «Настройки» -> «Настройки профиля» -> «API-ключ»:

Отправить HTTP-запрос можно множеством инструментов: начиная от исполняемых скриптов, заканчивая специальными программами. Например, postman или curl. Работать с 1cloud API через Python мы будем в следующей статье, а сейчас посмотрим, как это всё работает через cURL и Postman.

Вот как будет выглядеть HTTP-запрос на получение списка виртуальных серверов 1cloud:

cURL Postman
curl -X GET -H 'Content-Type: application/json' -H 'Authorization: Bearer XXX…' "https://api.1cloud.ru/server" GET /server HTTP/1.1 Host: api.1cloud.ru Content-Type: application/json Authorization: Bearer XXX…

В ответ мы получим JSON со списком серверов следующего типа (некоторые поля удалены для сокращения длины сообщения):

[
    {
        "ID": 945993,
        "Name": "Server",
        "State": "Active",
        "IsPowerOn": true,
        "CPU": 2,
        "RAM": 2048,
        "HDD": 40,
        "IP": "188.227.17.34",
        "Image": "Ubuntu18.04x64",
        "IsHighPerformance": false,
        "HDDType": "SSD",
        "PrimaryNetworkIp": "188.227.17.34",
        "LinkedNetworks": [],
        "DCLocation": "SdnSpb",
        "LinkedSshKeys": [],
        "DateCreate": "2023-04-26T14:25:38.867"
    }
]

Хорошо, с GET запросами всё просто, куда интереснее дела обстоят с PUT и POST запросами. Вместе с заголовками нам нужно передать еще и тело сообщения (body) с определенными ключами и значениями, которые строго определены в документации к 1cloud API.

Вот пример HTTP-запроса на создание сервера в ЦОДе Xelent:

cURL Postman
curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Bearer XXX…' "https://api.1cloud.ru/server" -d '{ "Name": "testapi1", "CPU":2, "RAM":2048, "HDD":40, "ImageID": "3", "HDDType":"SSD", "DCLocation":"SdnSpb", "isHighPerfomance":"false"'} POST /server HTTP/1.1 Host: api.1cloud.ru Content-Type: application/json Authorization: Bearer XXX… {"Name": "PM_test_api", "CPU":2, "RAM":2048, "HDD":40, "ImageID": "3", "HDDType":"SSD", "DCLocation":"SdnSpb", "isHighPerfomance":"false"}

В ответ мы получим JSON с параметрами созданного сервера:

{
    "ID": 947517,
    "Name": "testapi1",
    "HostName": null,
    "State": "New",
    "IsPowerOn": false,
    "CPU": 2,
    "RAM": 2048,
    "HDD": 40,
    "IP": "",
    "AdminUserName": null,
    "AdminPassword": null,
    "Image": "WinServer2012R2x64En",
    "IsHighPerformance": false,
    "HDDType": "SSD",
    "PrimaryNetworkIp": "",
    "LinkedNetworks": [],
    "DCLocation": "SdnSpb",
    "ImageFamily": "Windows",
    "LinkedSshKeys": [],
    "DateCreate": "2023-04-27T11:56:15.1221137+03:00"
}

Эти данные пока не очень полезны (кроме ID-сервера), так как не содержат данные для подключения. Для получения этой информации после создания сервера нужно отправить HTTP-запрос на получение списка серверов — там будет информация для подключения к серверам.

Если нужно удалить сервер — достаточно отправить DELETE HTTP-запрос на URL https://api.1cloud.ru/server/{id}, где id подменяется на числовое id-сервера. Например, удалить сервер 945993 можно так:

cURL Postman
curl -X DELETE -H 'Content-Type: application/json' -H 'Authorization: Bearer XXX…' "https://api.1cloud.ru/server/945993" DELETE /server/{id} HTTP/1.1
Host: api.1cloud.ru
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Authorization: Bearer XXX…

Итак, с помощью 1cloud API вы можете совершать множество действий с серверами и другими ресурсами облачного провайдера. Но использовать для управления ресурсами cURL или PostMan — это не самый удобный путь. В следующей статье мы покажем как можно использовать 1cloud API более эффективно с помощью Python, а пока подведем итог.

Кратко о API и REST API

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

REST API или RESTful API — это стиль написания API-запросов, который использует стандартные HTTP-методы для работы. Часто при работе с REST используют понятие CRUD-модели, каждому элементу из которых соответствует свой HTTP-метод:

  1. С — create (POST);
  2. R — read (GET);
  3. U — update (PUT);
  4. D — delete (DELETE).

Главной отличительной особенностью REST API является то, что он направлен на использование ресурсов, то есть у каждого ресурса есть свой URL, с которым мы можем взаимодействовать с помощью HTTP-методов. Обычно API URL имеют такой вид: базовый URI + URI ресурса. Хорошим примером является URL 1cloud API: базовый URI — https://api.1cloud.ru/ + URI ресурса — /server/, /dns/, /monitoring/.

Работать с REST API можно как с помощью специализированных программ: cURL, PostMan, так и с помощью различный ЯП библиотек:

  1. Go:
    • net/http: Встроенный пакет для работы с HTTP, включая отправку и получение HTTP-запросов.
    • resty: Простая и легкая библиотека для выполнения HTTP-запросов с функциями, такими как автоматическое повторение запросов и поддержка таймаутов.
  2. Rust:
    • reqwest: Асинхронная библиотека для выполнения HTTP-запросов с поддержкой множества функций, таких как JSON, отправка форм и пр.
    • hyper: Низкоуровневый, асинхронный клиент и сервер HTTP, позволяющий создавать кастомные HTTP-запросы и обработчики.
  3. C++:
    • libcurl: Многофункциональная библиотека для работы с URL, включая поддержку HTTP, HTTPS и других протоколов.
    • cpprestsdk (C++ REST SDK, также известная как Casablanca): Библиотека для создания клиентов и серверов REST на C++.
  4. C#:
    • HttpClient: Встроенный класс в .NET Framework и .NET Core для отправки HTTP-запросов и получения HTTP-ответов от REST API.
    • RestSharp: Простая и популярная библиотека для работы с HTTP и RESTful веб-сервисами в C#.
  5. Python:
    • http.client (Python 3) / httplib (Python 2): Встроенная библиотека для работы с HTTP, предоставляющая классы для реализации HTTP-клиентов.
    • urllib: Встроенная библиотека для работы с URL, включая отправку HTTP-запросов. В Python 3, эта библиотека разделена на две части - urllib.request и urllib.parse.
    • aiohttp: Асинхронная библиотека для выполнения HTTP-запросов, основанная на asyncio и применяющаяся в асинхронных приложениях Python.
    • treq: Библиотека для работы с HTTP, основанная на Twisted и предоставляющая аналогичный requests интерфейс, но в асинхронном контексте.
    • httpx: Полнофункциональный асинхронный клиент HTTP для Python 3, предоставляющий поддержку HTTP/1.1 и HTTP/2.

В следующей статье мы рассмотрим примеры работы с 1cloud API через Python, с использованием стандартной библиотеки Python — requests.