Вернуться в блог
Журнал Adal Cloud

Webhooks для desktop-приложений: как получать события без собственного backend

Как доставлять облачные события в desktop-приложение без публичного IP и собственного сервера.

Опубликовано
Webhooks для desktop-приложений: как получать события без собственного backend

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

Через несколько минут обработка завершается. Сервис умеет сообщать об этом вебхуком: ему нужен URL, на который можно отправить HTTP-запрос.

И здесь возникает неудобный вопрос. Куда отправлять событие, если получатель — обычное приложение на ноутбуке? У него нет постоянного публичного адреса, пользователь может сменить Wi-Fi или закрыть крышку. А собственного backend у продукта до этого вообще не было.

В Adal Cloud такой поток можно организовать через публичный приём вебхуков и исходящее соединение с компьютера. Разберём, как это работает и какие обязанности остаются у desktop-приложения.

Почему localhost недостаточно

Desktop-приложение может запустить небольшой HTTP-обработчик, например на http://127.0.0.1:4587/webhooks. Для этого не нужно разворачивать отдельное серверное приложение: обработчик может быть частью локального процесса.

Но адрес 127.0.0.1 доступен только на самом компьютере. Если передать его облачному сервису как callback URL, он не станет адресом ноутбука пользователя.

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

При этом приложению нужна вполне небольшая возможность: узнать, что конкретная внешняя операция завершилась. Поднимать и сопровождать свой backend только ради приёма этих событий — заметное расширение инфраструктуры продукта.

Публичный URL в облаке, обработчик на компьютере

В Adal Cloud публичную точку входа предоставляет Сервер Adal Cloud. Его HTTPS URL указывается в настройках вебхуков внешнего сервиса. На компьютере работает Adal CLI, который устанавливает исходящее защищённое соединение и передаёт запросы локальному обработчику.

Облачный сервис │ HTTPS webhook ▼ Сервер Adal Cloud │ доставка через соединение, установленное CLI ▼ Adal CLI на компьютере пользователя │ локальный HTTP-запрос ▼ Desktop-приложение: 127.0.0.1:4587/webhooks │ ▼ Локальные данные и интерфейс

Для отправителя получатель всегда доступен по одному публичному URL. На стороне компьютера нужен доступ к Adal Cloud через исходящее соединение; открывать входящие порты на роутере и публиковать локальный обработчик не требуется. Этот маршрут описан в документации Adal CLI.

Серверная инфраструктура в такой схеме есть: её предоставляет Adal Cloud. «Без backend» означает, что разработчику desktop-приложения не нужно создавать и эксплуатировать собственный публичный backend для приёма вебхуков. Локальный обработчик и логика работы с событиями остаются в приложении.

Пример: облачная обработка документа

Вернёмся к приложению для документов. Допустим, выбранный сервис позволяет зарегистрировать webhook URL для нужного потока задач.

Приложение отправляет документ в обработку и сохраняет полученный job_id в своей локальной базе. Когда сервис завершает задачу, он отправляет на URL Сервера Adal Cloud событие с этим идентификатором.

Adal Cloud принимает запрос и передаёт его через CLI на локальный HTTP-обработчик. Приложение проверяет событие, находит задачу по job_id и сохраняет новый статус. Если результат нужно скачивать отдельно, оно обращается к API провайдера со своими учётными данными. Затем обновляет интерфейс или показывает уведомление.

В этой схеме вебхук сообщает о смене состояния. Сам документ, права доступа к нему и локальные действия по-прежнему контролирует приложение.

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

Как собрать первый маршрут

Для первой проверки достаточно одной установки приложения и одного потока событий:

  1. Добавьте локальный обработчик. Пусть приложение принимает вебхуки на 127.0.0.1:4587. Привяжите слушающий сокет к loopback-интерфейсу, чтобы он не становился доступен всей локальной сети.

  2. Создайте Сервер Adal Cloud. Выберите регион и постоянное хранение Requests, если нужны диагностика и доставка после перерыва в работе компьютера.

  3. Создайте Destination типа Adal CLI. Укажите URL локального обработчика. Проверьте итоговый путь запроса с учётом webhook URL провайдера и правил формирования URL в документации Destinations.

  4. Настройте отправителя. Зарегистрируйте публичный URL Сервера Adal Cloud для выбранного аккаунта или потока задач.

  5. Запустите приложение и подключите CLI. Используйте токен нужного Сервера. Локальный обработчик должен быть готов до начала доставки.

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

Последовательность создания ресурсов описана в быстром старте. На первом этапе CLI можно запускать отдельно. Если продукт должен управлять им как вспомогательным процессом, разработчику предстоит организовать его запуск, остановку, обновление и хранение конфигурации. Это часть интеграции desktop-приложения.

Что произойдёт, если приложение закрыто

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

Публичный приём в Adal Cloud не зависит от работающего ноутбука. При постоянном хранении принятый Request может ожидать последующей доставки в пределах retention. Для доставки накопленных запросов после подключения CLI должна быть включена настройка Deliver pending requests on connect. Destination должна существовать, CLI — подключиться к нужному Серверу, а локальный обработчик — быть доступен.

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

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

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

Приём события нужно отделить от действий в интерфейсе

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

Для локального приложения удобна такая последовательность: проверить запрос, надёжно сохранить событие или изменение состояния в локальной базе и затем вернуть успешный HTTP-ответ. Длительные операции и обновление интерфейса можно выполнять после этого, опираясь на сохранённое состояние.

Так закрытие окна между приёмом события и показом уведомления не превращается в потерю задачи. При следующем запуске приложение увидит её в базе. Принципы защиты от повторов разобраны в статье «Почему вебхуки нужно обрабатывать идемпотентно».

Что меняется при распространении приложения

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

Для персональной утилиты пользователь может настроить собственный Сервер Adal Cloud и подключить свой поток событий. В массовом продукте нужно заранее определить, кому принадлежат Серверы, как выдаются и отзываются токены и как события одного пользователя отделяются от другого.

Один общий Сервер с несколькими Destinations не решает эту задачу: один входящий Request доставляется во все его Destinations. Такая конфигурация сама по себе не выбирает получателя по user_id в JSON.

Нельзя также положить общий привилегированный токен или общий секрет провайдера в дистрибутив и считать его скрытым. Desktop-приложение работает на машине пользователя, который контролирует её окружение. Учётные данные должны соответствовать правам конкретного пользователя или установки.

Проверка подписи отправителя остаётся обязанностью обработчика. Для задержанных событий нужно учитывать правила провайдера: если подпись имеет ограниченный допустимый возраст, сохранённый вебхук может не пройти проверку после длительного офлайна. Доставка через Adal Cloud не обновляет подпись отправителя.

Где проходит граница сценария

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

Если операция обязана завершаться немедленно при выключенном компьютере, её исполнитель должен работать вне desktop-приложения. Adal Cloud может принять и сохранить запрос, но выполнить локальный код на выключенной машине невозможно.

Отдельной проверки требуют провайдеры с синхронным challenge-response при регистрации URL. Приём запроса Сервером Adal Cloud и последующая доставка в приложение — разные этапы: ответ локального обработчика нельзя считать синхронным ответом внешнему отправителю.

Для подходящего сценария результат прост: приложение сохраняет локальный интерфейс, данные и обработку, а Adal Cloud предоставляет постоянный публичный адрес и доставку событий до компьютера. Вебхуки становятся доступным способом связи с desktop-продуктом без отдельного собственного backend только ради callback URL.

Другие материалы блога Adal Cloud

Читайте об обновлениях продукта, работе с вебхуками и инженерных решениях.

Вернуться в блог