Как исправить ошибку 400 (Bad Request - Invalid Verb) при отправке PUT-запроса по HTTPS в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними REST API и веб-сервисами нередко возникают сбои при переходе с не защищенного протокола HTTP на защищенное соединение HTTPS. Разберем типичную ситуацию: до внедрения SSL-сертификата выгрузка данных из 1С с помощью HTTP-запросов метода PUT работала исправно, однако после включения HTTPS сервер начинает возвращать ошибку 400 Bad Request - Invalid Verb.

Рассмотрим причину возникновения этой ошибки и изучим проверенные способы ее устранения в платформе 1С:Предприятие 8.3.

Выясняем причину ошибки

Проанализируем текст ответа, который возвращает веб-сервер при отправке запроса через 1С:

HTTP Error 400. The request verb is invalid.

Данная ошибка генерируется веб-сервером (часто IIS или защитным драйвером HTTP.sys в ОС Windows) еще до того, как запрос передается конечному веб-приложению. Это означает, что SSL-соединение между 1С и сервером успешно установлено (объект ЗащищенноеСоединениеOpenSSL отработал штатно), однако сам HTTP-пакет сформирован платформой 1С или обработан сетевым стеком так, что сервер не может корректно распознать HTTP-метод (глагол PUT).

Причины такого поведения кроются в особенностях работы встроенных методов платформы 1С при сочетании защищенного соединения HTTPS, авторизации (например, NTLM/Domain) и служебных заголовков, отправляемых платформой по умолчанию.

Способ 1. Замена метода Записать() на ВызватьHTTPМетод()

В платформе 1С:Предприятие 8.3 для отправки данных методом PUT традиционно используется метод объекта HTTPСоединение под названием Записать(). Однако при работе через SSL этот метод может добавлять или модифицировать служебные заголовки запроса, что приводит к сбою на стороне IIS или Nginx.

Решением является использование более низкоуровневого и универсального метода ВызватьHTTPМетод(), в котором HTTP-глагол передается в явном виде.

Посмотрим на исходный код, выбивавший ошибку 400:


ИмяСервера = "api.myservice.ru";
Порт = 443;
ИмяМетода = "/api/v1/goods/" + GUIDОбъекта;

HTTP = Новый HTTPСоединение(ИмяСервера, Порт, , , , , Новый ЗащищенноеСоединениеOpenSSL(), Истина);

ЗаголовокЗапросаHTTP = Новый Соответствие();
ЗаголовокЗапросаHTTP.Вставить("Content-Type", "application/json-patch+json");

ЗапросPUT = Новый HTTPЗапрос(ИмяМетода, ЗаголовокЗапросаHTTP);
ЗапросPUT.УстановитьИмяФайлаТела(ПутьКФайлу);

// Данный метод вызывал ошибку HTTP 400
ОтветСервера = HTTP.Записать(ЗапросPUT);

Перепишем блок отправки запроса с использованием метода ВызватьHTTPМетод():


ИмяСервера = "api.myservice.ru";
Порт = 443;
ИмяМетода = "/api/v1/goods/" + GUIDОбъекта;

HTTP = Новый HTTPСоединение(ИмяСервера, Порт, , , , , Новый ЗащищенноеСоединениеOpenSSL(), Истина);

ЗаголовокЗапросаHTTP = Новый Соответствие();
ЗаголовокЗапросаHTTP.Вставить("Content-Type", "application/json-patch+json");

ЗапросPUT = Новый HTTPЗапрос(ИмяМетода, ЗаголовокЗапросаHTTP);
ЗапросPUT.УстановитьИмяФайлаТела(ПутьКФайлу);

// Используем универсальный метод для передачи HTTP-глагола PUT
ОтветСервера = HTTP.ВызватьHTTPМетод("PUT", ЗапросPUT);

Важное примечание: В некоторых релизах платформы 1С из-за нюансов синтаксического анализатора при вызове метода ВызватьHTTPМетод может потребоваться передача строки метода с завершающим пробелом: HTTP.ВызватьHTTPМетод("PUT ", ЗапросPUT);. Если первый вариант возвращает ошибку, рекомендуем проверить передачу строки с пробелом.

Способ 2. Отключение заголовка Expect: 100-continue

При отправке запросов с файлом или большим телом через HTTPS сетевой стек платформы 1С может по умолчанию добавлять заголовок Expect: 100-continue. При выполнении SSL-рукопожатия и доменной NTLM-аутентификации IIS ожидает повторной передачи заголовков и сбрасывает соединение с ошибкой Invalid Verb.

Чтобы отключить двухэтапную передачу, явно передадим пустой заголовок Expect в объекте HTTPЗапрос:


ЗаголовокЗапросаHTTP = Новый Соответствие();
ЗаголовокЗапросаHTTP.Вставить("Content-Type", "application/json");
ЗаголовокЗапросаHTTP.Вставить("Expect", ""); // Отключаем заголовок Expect

ЗапросPUT = Новый HTTPЗапрос(ИмяМетода, ЗаголовокЗапросаHTTP);
ЗапросPUT.УстановитьТелоИзСтроки(ДанныеJSON);

ОтветСервера = HTTP.ВызватьHTTPМетод("PUT", ЗапросPUT);

Способ 3. Использование системного объекта WinHTTP (для Windows)

Если штатные средства 1С продолжают вызывать конфликт с веб-сервером из-за особенностей доменной авторизации или SSL-сертификатов, разберем альтернативный вариант выгрузки через системный COM-объект WinHttp.WinHttpRequest.5.1.


ИмяСервера = "api.myservice.ru";
ИмяМетода = "/api/v1/goods/" + GUIDОбъекта;
URL = "https://" + ИмяСервера + ИмяМетода;

HTTPОбъект = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
HTTPОбъект.Open("PUT", URL, Ложь); // Ложь - синхронный вызов

// При необходимости включаем использование системных учетных данных для NTLM
HTTPОбъект.SetAutoLogonPolicy(0); 

HTTPОбъект.SetRequestHeader("Content-Type", "application/json");
HTTPОбъект.Send(ДанныеJSON);

КодСостояния = HTTPОбъект.Status;
ТекстОтвета  = HTTPОбъект.ResponseText;

Подведем итоги

  1. Ошибка 400 Bad Request - Invalid Verb при работе с HTTPS указывает на то, что веб-сервер не смог прочитать метод HTTP-запроса из-за искажения пакета на этапе SSL-согласования.
  2. Основным решением в 1С является переход от специализированного метода HTTPСоединение.Записать() к универсальному вызову HTTPСоединение.ВызватьHTTPМетод("PUT", ...).
  3. Дополнительно рекомендуется явно передавать пустой заголовок Expect: "" для предотвращения проблем с NTLM-авторизацией и двухэтапной загрузкой данных по HTTPS.
← На главную