При интеграции 1С со сторонними системами или веб-сервисами разработчики часто сталкиваются с тем, что сервер возвращает ошибку 400 Bad Request (Плохой запрос). Рассмотрим подробнее причины такого поведения и разберем по шагам, как правильно формировать параметры HTTP-запроса, чтобы соединение прошло успешно.
Проанализируем частую ошибку на конкретном примере. При инициализации структуры отправки разработчик может передать в параметры следующие значения:
СтруктураОтправки.Вставить("Сервер", "192.168.65.140");
СтруктураОтправки.Вставить("Порт", 443);
СтруктураОтправки.Вставить("АдресРесурса", "https://192.168.65.140/Working_KuznecovIV/hs/APIService/V1/SoglasovanieObmenDO");
В коде создания запроса эти параметры передаются в объекты 1С:
HTTPСоединение = Новый HTTPСоединение(Сервер, Порт, Логин, Пароль, , , SSL);
HTTPЗапрос = Новый HTTPЗапрос(МетодСервиса);
HTTPЗапрос.АдресРесурса = АдресРесурса;
Выясним причину ошибки в данном подходе. Объект HTTPСоединение уже устанавливает связь с конкретным хостом (IP-адресом) и портом. Когда мы инициализируем HTTPЗапрос, свойство АдресРесурса должно содержать только относительный путь до конкретного метода (URI), а не полный URL с протоколом и доменом.
Если веб-сервер (IIS, Nginx или Apache) получает в строке запроса дублирующийся протокол или IP-адрес внутри самого URI, он не может корректно разобрать синтаксис и мгновенно возвращает статус 400.
Посмотрим на исправленный вариант параметров. Из адреса ресурса необходимо исключить протокол (https://) и адрес сервера (192.168.65.140):
// Правильное формирование адреса ресурса:
СтруктураОтправки.Вставить("АдресРесурса", "/Working_KuznecovIV/hs/APIService/V1/SoglasovanieObmenDO");
Оставив только путь к базе и сервису, мы решаем главную проблему, из-за которой сервер отклонял запрос.
Если после исправления адреса ресурса сервер продолжает возвращать 400-й код, проанализируем другие распространенные нюансы работы с HTTP-запросами в 1С.
Если в АдресРесурса передаются GET-параметры (например, ?doc=Договор аренды), веб-серверы строго относятся к пробелам и кириллическим символам в URL. Любые подобные значения обязательно нужно кодировать. Применим встроенную функцию 1С: КодироватьСтроку(ВашаСтрока, СпособКодированияСтроки.КодировкаURL).
Обратим внимание на конкатенацию (склейку) строк при динамическом формировании адреса. Часто возникает опечатка в виде двойных слешей (например, /Working_KuznecovIV//hs/). Строгие веб-серверы расценят такой URL как некорректный и вернут ошибку еще до того, как запрос попадет в обработчик HTTP-сервиса 1С.
Ошибка часто возникает на этапе парсинга JSON принимающей стороной. Разберем основные проблемы тела запроса:
Content-Type. Если в заголовке указано application/json-rpc, а сервер ожидает строгий application/json (например, при использовании конструктора API для обмена в формате JSON), встроенные парсеры фреймворков отклонят тело с ошибкой 400.Если в запросе передаются дополнительные пользовательские заголовки (включая специфические заголовки для передачи GUID), наличие в них спецсимволов заставит сервер прервать соединение с ошибкой.
Иногда ошибку 400 генерирует не целевая база 1С, а промежуточный прокси-сервер. Такое случается, если превышен максимальный размер тела запроса (например, отправляется огромный файл в JSON) или сформирован слишком длинный URL (при передаче массива данных методом GET).
Рассмотрим лучший способ локализации ошибки 400 — в этом поможет инструмент для анализа HTTP-запросов в 1С. Веб-сервер или сам HTTP-сервис часто прикрепляет текстовое пояснение причины сбоя в тело ответа. Вместо того чтобы просто выводить код состояния на экран, прочитаем тело ответа сервера при помощи метода ПолучитьТелоКакСтроку().
Добавим в код обработку статуса ответа:
Попытка
РезультатВыполнения = HTTPСоединение.ВызватьHTTPМетод(МетодСервиса, HTTPЗапрос);
Если РезультатВыполнения.КодСостояния = 400 Тогда
ТекстОшибки = РезультатВыполнения.ПолучитьТелоКакСтроку();
Сообщить("Запрос отклонен (Ошибка 400). Детали от сервера: " + ТекстОшибки);
Иначе
Сообщить("Успешно. Код: " + РезультатВыполнения.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Внутренняя ошибка вызова соединения: " + ОписаниеОшибки());
КонецПопытки;
Проанализируем этот подход: если ошибка кроется в невалидном JSON или неправильных параметрах, сервер текстом ответит, что именно ему "не понравилось" (например, "The JSON text is not valid"). Это позволит моментально обнаружить и исправить проблему в структуре формируемых данных.