HTTP-клиент 1С: таймаут — часть бизнес-логики

Запрос, который «просто отправляет документ», однажды завис на 20 минут. Кассир нажал кнопку ещё три раза — и партнёр получил четыре заявки.

У внешнего вызова всегда есть две независимые части: транспорт и бизнес-результат. Ответ 200 означает, что сервер сумел ответить по HTTP; он не гарантирует, что заявка принята. Ошибка соединения, наоборот, не доказывает, что операция не выполнилась: сервер мог сохранить заявку и потерять ответ на обратном пути.

Сначала классифицируем исходы

  • 2xx: читаем тело и проверяем прикладной статус.
  • 400/422: запрос не пройдёт после простого повтора; данные уходят на исправление.
  • 401/403: останавливаем поток и проверяем секрет или права.
  • 429: уважаем ограничение частоты и Retry-After.
  • 5xx и сетевой сбой: возможен ограниченный повтор, только если операция идемпотентна.

Эту таблицу полезно согласовать с владельцем API до разработки. Без неё программист невольно превращает все ошибки в один текст «сервис недоступен», хотя оператору нужны разные действия.

Один вызов — один объект результата

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

Функция ОтправитьЗаявку(ТелоJSON, КлючИдемпотентности) Экспорт
    Соединение = Новый HTTPСоединение("partner.example", 443,,,, 20,
        Новый ЗащищенноеСоединениеOpenSSL);

    Запрос = Новый HTTPЗапрос("/api/v1/requests");
    Запрос.Заголовки.Вставить("Content-Type", "application/json");
    Запрос.Заголовки.Вставить("Idempotency-Key", КлючИдемпотентности);
    Запрос.УстановитьТелоИзСтроки(ТелоJSON, КодировкаТекста.UTF8);

    Попытка
        Ответ = Соединение.ОтправитьДляОбработки(Запрос);
    Исключение
        Возврат Новый Структура("Успех,МожноПовторить,Код,Сообщение",
            Ложь, Истина, 0, "Сетевой сбой");
    КонецПопытки;

    Успех = Ответ.КодСостояния >= 200 И Ответ.КодСостояния < 300;
    МожноПовторить = Ответ.КодСостояния = 429
        Или Ответ.КодСостояния >= 500;
    Возврат Новый Структура("Успех,МожноПовторить,Код,Сообщение",
        Успех, МожноПовторить, Ответ.КодСостояния, "Ответ внешнего API");
КонецФункции

Таймаут 20 секунд здесь не универсальная рекомендация. Его выбирают по пользовательскому сценарию и договорённости с партнёром. Для кнопки в форме даже 20 секунд мучительно долго; такую операцию лучше поставить в очередь и показать статус. Для ночной сверки допустим другой бюджет времени.

Повторяем не «три раза», а по политике

Мгновенные повторы создают дополнительную нагрузку именно в момент аварии. Используем возрастающие интервалы, например 30 секунд, 2 минуты, 10 минут, и добавляем небольшой случайный разброс. Число попыток и следующую дату храним вместе с заданием, а не в памяти фонового процесса.

Повтор POST безопасен только при поддержке ключа идемпотентности. Один и тот же ключ отправляется при всех попытках одной бизнес-операции. Новый ключ после таймаута уничтожает защиту: партнёр справедливо сочтёт запрос новым.

Секреты и журнал

Токен должен жить в защищённой настройке, а не в модуле и не в пользовательском параметре. В журнале достаточно имени интеграции, correlation ID, HTTP-кода, длительности и номера попытки. Заголовок Authorization и полное тело запрещены. Для отладки сохраняют обезличенный фрагмент или хеш полезной нагрузки.

Минимальный тест клиента включает пять заглушек: быстрый 200, медленный ответ дольше таймаута, 422 с понятной ошибкой, 429 с паузой и 503 после того, как партнёр уже сохранил заявку. Последний сценарий показывает, почему транспортный сбой нельзя трактовать как отсутствие результата.

Практика: нарисуйте таблицу решений для вашего API. Для каждого класса ответа укажите: повторяем ли запрос, когда, сколько раз, что видит пользователь и кто получает уведомление.

Проверьте себя
1. Когда допустим автоматический повтор POST после сетевого сбоя?
AВсегда, POST безопасен
BТолько ночью
CКогда операция защищена устойчивым ключом идемпотентности
DЕсли тело меньше 1 МБ
2. Что означает HTTP 422 в согласованном API?
AОбычно данные не прошли прикладную проверку
BНужно немедленно повторить запрос
CУ клиента нет сети
DСервер успешно создал объект
3. Что безопасно записать в журнал интеграции?
AПолный Authorization
BПароль сервисной учётной записи
CCorrelation ID, длительность и HTTP-код
DПолное тело с персональными данными