Привет, Хабр! На связи хостинг-провайдер SpaceWeb. В этой статье расскажем, как работает клиентский API у нас, почему для него мы выбрали технологию JSON-RPC и чем она нам так нравится. Историей делятся Виталий Киреев, руководитель R&D, и Алексей Шашкин, продакт-менеджер.
Бэкграунд проекта: API как панель управления
Мы начали развивать API для наших продуктов еще 6 лет назад. Тогда у нас была задача сделать панель управления, которая отвечала бы современным стандартам: мобильное приложение, SPA. Но реализовать это «в лоб» было сложно, потому что у нас был большой legacy-проект — монолит с парадигмой MVC. Все инструменты внутри были очень связаны, правки было вносить практически невозможно.
Тогда мы решили пойти по другому пути: полностью отделить черный ящик, который работает со всеми нашими сервисами, дать ему внешнее API и подключать к нему клиентов. Такой подход позже помог нам из панели управления выделить отдельный клиентский инструмент — API.
Архитектура проекта была изначально заложена правильно: бэкенд-слой был выделен отдельно и не связан с фронтенд-частью, а значит и клиент мог быть абсолютно любым. Для того, чтобы вызвать API, можно использовать разные транспорты: и HTTP, и брокер сообщений на RabbitMQ. И каждый слой сервисов имеет эффективное покрытие юнит-тестами.
API для клиентов
Работать над выделенным API мы начали после нескольких десятков запросов на мобильное приложение от клиентов. Для приложения нужен был универсальный интер��ейс, который позволил бы получить доступ ко всем услугам сразу, поэтому реализовывать задачу мы решили тоже через API.
За основу взяли API для панели управления. При этом мы понимали, что какие-то методы нужно зарефакторить и изменить по количеству параметров, потому что они могут быть не очевидны для клиента. Например, в API панели управления есть возвращаемые значения, которые нужны для отображения значений. А какому-то разработчику они будут не нужны.
Важно было сделать публичный API таким, чтобы он не был заточен только под нашу компанию и нашу панель управления, а был полезен широкому кругу разработчиков. В этом была главная сложность в адаптации публичного API.
Какую технологию выбрали для API SpaceWeb
Для доступа к API используется протокол HTTP/HTTPS, а данные передаются в виде JSON-RPC по методу POST. Вызываемый метод API содержится в запросе вместе с параметрами вызова.
Мы выбрали именно JSON-RPC, потому что было важно отделить слой бизнес-логики от слоя протокола. Его преимущество в том, что заголовки ответов читаются однозначно для нас и для клиента. Например, если пришел ответ 500, то это значит это проблема на серверной стороне. Если ответ пришел 200, но внутри ответа содержится расшифровка JSON-RPC ошибки, значит эта ошибка в приложении, слой бизнес-логики.
А вот в Rest API все работает не так. Если возникает ошибка, то может приходить заголовок с кодом 500 и нам будет непонятно: это сам сервер упал или ответ от API с ошибкой 500. То есть здесь смешивается логика транспорта и приложения.
Как работает клиентский API
Авторизация и токен
В большинстве ��лучаев для доступа к API потребует токен. Получить его можно после авторизации, отправив запрос на специальный url: https://api.sweb.ru/notAuthorized/. Выглядит этот запрос вот так:
{
"jsonrpc": "2.0",
"method": "getToken",
"params": {
"login": "<ваш логин>",
"password": "<ваш пароль>"
}
}Сам токен будет содержаться в ответе в параметре result:
{
"jsonrpc": "2.0",
"id": "20220505104244.40FxsQ16Ff",
"result": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}Запрос
Для доступа к API запрашивается отдельный url: https://api.sweb.ru/domains/. При этом запрос содержит следующие заголовки:
Content-Type: application/json; charset=utf-8
Accept: application/json
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxВсе запросы, кроме тех, которые адресованы к общедоступным методам, должны содержать токен авторизации Authorization: Bearer.
Тело запроса может иметь вид:
{
"jsonrpc": "2.0",
"method": "move",
"params": {
"domain": "vpstest.ru"
},
"id": "20183994338.43VSEkfGFh",
"user": "xxxxxxxxx"
}В этом запросе имеются следующие параметры:
jsonrpc — текущая версия JSON-RPC. Это обязательный параметр.
method — метод объекта Domains. Если он не передан, то система назначит метод объекта по умолчанию.
params — объект параметров метода (ключ элемента объекта - имя параметра).
id — уникальный идентификатор запроса. Если он в запросе не содержится, то id будет сформирован на стороне API.
user — логин пользователя, который отправляет запрос. Носит только информационный характер, сверяется со значением сессии токена и в случае расхождения приводит к ошибке авторизации.
Ответ
Если запрос к API отработан успешно, то система возвращает результат в виде JSON:
{
"jsonrpc": "2.0",
"id": "20183995523.MO4E9baKRr",
"result": {
"balance": {
"real_balance": 500,
"bonus_balance": 0
}
}
}В ответе содержатся обязательные параметры:
jsonrpc — текущая версия JSON-RPC;
version — текущая версия клиента;
result — результат, который возвращает вызванный метод;
id — уникальный идентификатор ответа, если был в запросе, то совпадает с ним.
Если при обработке запроса возникает ошибка, то форма ответа будет такой:
{
"jsonrpc": "2.0",
"version": "0.1",
"id": "20183910121.UPNWsDxwmn",
"error": {
"code": -32601,
"message": "Object not found"
}
}Расширенное сообщение о результатах работы метода
Некоторые методы, помимо успешного или неуспешного ответа, должны передать клиенту кастомизированное сообщение или данные. Для таких ответов применяется общий тип ExtendedResult. Выглядят такие ответы следующим образом:
{
"jsonrpc": "2.0",
"id": "20183995523.MO4E9baKRr",
"result": {
"extendedResult": {
"code": 1,
"message": "Заявка #180047823 принята в работу",
"data": []
}
}
}
{
"jsonrpc": "2.0",
"id": "20183995523.MO4E9baKRr",
"result": {
"extendedResult": {
"code": 0,
"message": "Зона .child не поддерживается для регистрации",
"data": []
}
}
}Здесь code 1 означает успешное выполнение, а 0 ошибку. А поле data (объект дополнительных данных) может оставаться пустым.
К каким данным дает доступ API
Функции, к которым клиент может получить доступ после авторизации, разделены на несколько категорий в соответствии с бизнес-логикой: виртуальный хостинг, VPS, домены, партнерская программа, финансовый сервис. Внутри каждого раздела тоже есть иерархическая система из объектов, которые объединяют несколько функций — отдельных методов.
Реальный кейс использования API
Основные пользователи API — веб-мастера, которые управляют сразу несколькими аккаунтами разных клиентов. Для них это очень удобная фича.
Если бы не было API, работа выглядела бы так: заходишь в панель управления одного клиента, выгружаешь данные (например, о балансе, доменах и SSL с приближающейся датой окончания регистрации), анализируешь их в таблице. А если нужно посмотреть метрики другого клиента или сравнить их, выходишь из предыдущего аккаунта и заходишь в следующий. И так несколько раз.
API позволяет сократить время на переключения между аккаунтами. Веб-мастер с помощью техно��огии может создать собственный скрипт и прикрутить его к своему дашборду, чтобы видеть информацию со всех аккаунтов сразу. Например, с помощью API удобно следить за датой окончания регистрации доменов по всем аккаунтам сразу.
В нашем API используются разные методы для управления аккаунтами, подробно мы их описывали в документации. Один из популярных — https://api.sweb.ru/pay/ метод index, он дает информацию о балансе аккаунта, количестве доменных бонусов, за счет которых можно бесплатно продлевать и регистрировать домены, статус аккаунта и ожидаемую дату блокировки.
Пример запроса на url: https://api.sweb.ru/pay
{
"jsonrpc":"2.0"
"id":"715670275654947.SpiAFUtJpx"
"method":"index"
"params":{}
}Пример ответа:
{
"jsonrpc":"2.0"
"id":"715670275654947.SpiAFUtJpx"
"params":[
{
"balance":{
"real_balance":30
"bonus_balance":0
}
"auto_payment_enable":0
"isAutopaymentEnable":1
"domainBonuses":0
"status":"active"
"blockInfo":{
"days_date":"07.02.2023"
"days":0
"days_word":"дней"
}
"blockedMoney":0
"deferment":{
"show":false
"value":0
}
"edgeDate":"2022-11-14"
}
]
}Важная часть нашего API — возможность для клиентов управлять партнерской программой. Можно получать информацию о клиентах из партнерки, текущем балансе, настроить реферальные сайты.
Для верифицированных клиентов доступны методы, с помощью которых можно создавать отдельные аккаунты под привлеченных клиентов — createOrderVh, checkLogin, createOrderVip и другие.
Используя их, можно сделать форму регистрации, с помощью которой, не переходя на сайт SpaceWeb, можно зарегистрироваться на виртуальном хостинге или VPS. А созданный аккаунт будет автоматически подключен к партнерской программе. У конкурентов такого нет.
Планы по развитию API
В первую очередь будем расширять количество методов. Добавим управление почтой и DNS, методы для управления облачными платформами: балансировщиком, базой данных и бэкапами. Подготовим открытые коды для клиентов — их можно будет интегрировать в любые сервисы.
Еще хотим внедрить в API потоковые данные, например снэпшоты VPS. Они весят достаточно много, но мы хотим попробовать перейти на спецификацию, которая поддерживает передачу именно потоковых данных.
А вы используете API при работе с хостинг-провайдерами? Каких методов вам не хватает?
