Skip to main content
Каждая задача в асинхронном API может быть доставлена двумя способами. Вы можете отправлять запросы к GET /v1/task/{task_id} до её завершения или передать WideRouter URL https и позволить результату прийти к вам. Второй способ — это callback, и он является свойством самого API задач, а не какой-либо отдельной модели: одно и то же поле, одинаковые данные и одни и те же правила применяются как к изображению Nano Banana, так и к видео Grok Imagine.
Для опроса требуется ваш API-ключ в каждом запросе. Для callback он не нужен. Получателем является URL, размещённый вами; WideRouter вызывает его, поэтому нет учётных данных, которые нужно загружать, передавать или указывать с ошибкой. Если ваш обработчик опроса когда-либо отвечает 401 или у вас выполняются тысячи задач, эта страница для вас.

Одно поле при отправке

Добавьте callback_url рядом с model и input. Ничего другого в запросе не изменится, а в ответе на отправку будет тот же идентификатор задачи, который вы получили бы в обычном случае.
Оба поля проверяются во время отправки, поэтому ошибка приводит к немедленному сбою, а не к созданию задачи, которая незаметно так и не отправит ответ. Некорректный URL — это 400 invalid_callback_url; некорректный секрет — это 400 invalid_params, если param имеет значение callback_secret:

Что WideRouter отправляет вам

Один POST на каждую задачу, Content-Type: application/json, когда задача достигает конечного состояния. Три заголовка позволяют выполнить маршрутизацию и аутентификацию до разбора тела: Тело — это объект задачи, байт в байт совпадающий с тем, что GET /v1/task/{task_id} возвращает в данный момент. Один парсер обслуживает и callback, и путь опроса.
Для неуспешной задачи выполняется возврат средств до отправки callback, поэтому task.failed также служит для вас сигналом о том, что списание было отменено. Выходные файлы называются по идентификатору задачи, поэтому их легко сохранять без переименования.

Правила доставки

При проектировании следует учитывать два важных последствия:
  • Обеспечьте идемпотентность. Повторная попытка после медленного ответа 200 означает, что одна и та же задача может поступить дважды. Используйте id в качестве ключа обработчика.
  • Предусмотрите резервный вариант с опросом для задержавшихся задач. Сохраняйте идентификатор задачи во время отправки. Если callback не поступил через несколько минут после обычной задержки модели, один раз запросите состояние задачи. Callback оптимизирует задержку, но не гарантирует доставку.

Проверка подписи

При отправке передайте callback_secret, и каждый callback для этой задачи будет содержать X-Wide-Signature. Это доказывает два факта: запрос поступил от WideRouter, а тело не было изменено при передаче. Это не шифрование — тело содержит только общедоступные URL.
t — это Unix-время отправки callback. v1 — это hex(HMAC-SHA256(callback_secret, "<t>.<raw body>")): метка времени, точка, затем тело запроса в точности в том виде, в котором оно было получено.
1

Получите необработанное тело

Дайджест вычисляется по байтам. Разбор JSON и его повторная сериализация изменяют байты, поэтому прочитайте тело до того, как его обработает какой-либо фреймворк.
2

Повторно вычислите значение и сравните за постоянное время

Повторно создайте HMAC с тем же секретом и сравните его с помощью функции, выполняющей сравнение за постоянное время, а не с помощью ==.
3

Отклоняйте устаревшие метки времени

Отбрасывайте всё, для чего t отличается от показаний ваших часов более чем на 300 секунд в любом направлении. Именно это не позволяет повторно воспроизвести перехваченный callback позднее. Измеренное расхождение при тестировании составило около 3 секунд.
Без callback_secret заголовок подписи отсутствует, а непредсказуемый путь в callback_url — единственное, что защищает вас от поддельного статуса «завершено». В любом случае повторно прочитайте GET /v1/task/{task_id} с помощью вашего API-ключа, прежде чем скачивать результаты задачи или выполнять тарификацию: подпись подтверждает, кто отправил callback, а повторное чтение показывает, каков текущий статус задачи.

Обработчик-получатель на трёх языках

Каждый обработчик выполняет одни и те же пять действий: проверяет подпись для исходного тела запроса, проверяет заголовок события, немедленно подтверждает получение с помощью 200, передаёт идентификатор задачи в очередь и позволяет воркеру повторно прочитать задачу и скачать выходные данные. Функция verify — это функция из предыдущего раздела. Загрузка намеренно выполняется за пределами обработчика запроса, поскольку выходные данные могут занимать несколько мегабайт, а на ответ у вас есть десять секунд.
Воркер читает задачу с тем же ключом API, который используется для отправки. Ключ, загруженный для отправки, но не настроенный для пути чтения, — наиболее частая причина того, что обработчик получает идентификаторы задач, но не изображения: каждый ответ GET возвращает 401, тогда как каждый POST завершается успешно. Используйте один настроенный клиент для обоих действий.

Тестирование без сервера

Любой сервис инспекции запросов, который предоставляет общедоступный https URL, подходит в качестве временного приемника: отправьте задачу, указав этот URL в качестве callback_url, и наблюдайте, как объект задачи появляется в инспекторе. Когда вы будете готовы принимать запросы на собственной машине, туннель https к локальному порту выполнит ту же функцию. Помните, что URL должен быть доступен из интернета; адрес в локальной сети отклоняется при отправке задачи.

Скачивайте своевременно

URL вывода перестают работать через 24 часа после завершения задачи, а callback — самый ранний момент, когда вы узнаёте об их существовании. Получатель, который скачивает данные при поступлении, никогда не должен думать об истечении срока; тот, который лишь сохраняет URL и обращается к нему позже, в конечном итоге будет хранить ссылки, ведущие в никуда.

Следующие шаги

API асинхронных задач

Конверт, цикл опроса, состояния задач и таблица ошибок.

Быстрый старт

Отправьте, опросите и скачайте примерно за пять минут.