Часто при интеграции 1С с внешними веб-сервисами возникает ситуация, когда, казалось бы, правильно составленный POST-запрос возвращает непонятную ошибку 500 Internal Server Error без каких-либо пояснений в теле ответа. При этом аналогичный запрос из другого инструмента, например, из JavaScript в браузере, работает исправно. Давайте вместе разберемся, в чем может быть причина и как это исправить на конкретном примере, а для более глубокого изучения темы рекомендуем пройти интерактивный обучающий курс по работе с HTTP-запросами.
Проанализируем ситуацию: у нас есть код на 1С, который должен отправить данные на сервер, но он не работает. А также есть работающий пример на JavaScript, который успешно отправляет те же данные.
Рассмотрим первоначальный код на 1С, который приводил к ошибке.
// Переменные для примера
АдресСайта = "example.com";
АдресAPI = "/api/post";
ФайлJSON = "{""action"": ""getAllContragents"", ""secret"": ""08e09ac9dbc8e7a6205d1c0c82fdff1e""}"; // JSON в виде строки
// Код запроса
HTTPСоединение = Новый HTTPСоединение(АдресСайта);
ЗапросHTTP = Новый HTTPЗапрос(АдресAPI);
// Устанавливаем заголовок, который предполагает отправку JSON
ЗапросHTTP.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");
// А тело формируем как строку "ключ=значение"
ЗапросHTTP.УстановитьТелоИзСтроки("action=oneSActions" + "&data=" + ФайлJSON, КодировкаТекста.UTF8);
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(ЗапросHTTP); // Получаем HTTPОтвет.КодСостояния = 500
Ключевая ошибка здесь — несоответствие между заголовком Content-Type и форматом тела запроса. Мы сообщаем серверу, что отправляем данные в формате application/json, но на самом деле тело запроса представляет собой строку, похожую на данные веб-формы (key1=value1&key2=value2). Сервер, ожидая увидеть валидный JSON, не может разобрать полученные данные и возвращает общую ошибку 500.
Теперь посмотрим на работающий JavaScript-код. В нем для формирования данных используется объект FormData.
let f_data = new FormData();
f_data.append("action", "oneSActions");
f_data.append("data", JSON.stringify(json_data));
fetch(srv_url, {
method: 'POST',
body: f_data, // Отправка данных через FormData
});
Когда браузер отправляет данные, собранные через FormData, он автоматически устанавливает правильный заголовок Content-Type. В данном случае, так как файлы не передаются, это будет либо application/x-www-form-urlencoded, либо multipart/form-data. Именно этот формат и ожидает сервер.
Проблема ясна: нам нужно в 1С сформировать запрос так, как это делает браузер с FormData. Для этого необходимо изменить и заголовок, и способ формирования тела запроса.
Шаг 1. Устанавливаем правильный заголовок Content-Type
Сервер ожидает данные в формате, аналогичном отправке обычной HTML-формы. Для этого используется заголовок application/x-www-form-urlencoded. Изменим эту строку в нашем коде.
Шаг 2. Корректно формируем тело запроса
Тело запроса должно быть строкой, где пары "ключ=значение" разделены амперсандом (&). У нас два параметра: action и data. Значением параметра data является строка JSON. Соберем эту конструкцию.
Для надежности и правильного формирования JSON-строки из данных 1С лучше использовать специальные объекты ЗаписьJSON, а дополнительно убедиться в корректности данных поможет проверка на заполненность обязательных полей в строке JSON.
Шаг 3. Собираем итоговый код
Теперь объединим все исправления и дополнения в финальный, работающий вариант кода на 1С.
// 1. Подготовим данные, которые будут внутри JSON
ДанныеДляJSON = Новый Структура;
ДанныеДляJSON.Вставить("action", "getAllContragents");
ДанныеДляJSON.Вставить("secret", "08e09ac9dbc8e7a6205d1c0c82fdff1e");
// 2. Преобразуем структуру 1С в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляJSON);
СтрокаJSON = ЗаписьJSON.Закрыть();
// 3. Формируем тело запроса в формате x-www-form-urlencoded
// ВАЖНО: Если в строке JSON могут быть спецсимволы (&, =, ?),
// ее нужно дополнительно кодировать для URL. В данном примере это опущено для простоты,
// но в реальных задачах это может быть необходимо:
// СтрокаJSON = КодироватьСтроку(СтрокаJSON, СпособКодированияСтроки.URL);
ТелоЗапроса = "action=oneSActions" + "&data=" + СтрокаJSON;
// 4. Настраиваем и отправляем сам запрос
АдресСайта = "example.com";
АдресAPI = "/api/post";
HTTPСоединение = Новый HTTPСоединение(АдресСайта);
ЗапросHTTP = Новый HTTPЗапрос(АдресAPI);
// Устанавливаем ПРАВИЛЬНЫЙ заголовок
ЗапросHTTP.Заголовки.Вставить("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
// Устанавливаем тело из сформированной строки
ЗапросHTTP.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);
Попытка
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(ЗапросHTTP);
Сообщить("Код ответа сервера: " + HTTPОтвет.КодСостояния);
Если HTTPОтвет.КодСостояния = 200 Тогда
Сообщить("Ответ сервера: " + HTTPОтвет.ПолучитьТелоКакСтроку());
Иначе
Сообщить("Текст ошибки: " + HTTPОтвет.ПолучитьТелоКакСтроку());
КонецЕсли;
Исключение
Сообщить("Ошибка при отправке HTTP-запроса: " + ОписаниеОшибки());
КонецПопытки;
После замены заголовка на application/x-www-form-urlencoded и отправки тела в виде строки "action=oneSActions&data={...}" сервер успешно примет и обработает запрос.
Для полноты картины рассмотрим, как выглядел бы код, если бы сервер действительно ожидал данные в формате application/json. Подобная структура часто встречается, когда настраивается интеграция 1С с Google Таблицами или другие современные API. В этом случае все тело запроса должно быть одной большой JSON-строкой.
Предположим, API ожидает такую структуру:
{
"action": "oneSActions",
"data": {
"action": "getAllContragents",
"secret": "08e09ac9dbc8e7a6205d1c0c82fdff1e"
}
}
Тогда код на 1С для формирования такого запроса будет выглядеть следующим образом:
// 1. Собираем вложенную структуру данных в 1С
ВложенныеДанные = Новый Структура("action, secret", "getAllContragents", "08e09ac9dbc8e7a6205d1c0c82fdff1e");
ОбщиеДанные = Новый Структура;
ОбщиеДанные.Вставить("action", "oneSActions");
ОбщиеДанные.Вставить("data", ВложенныеДанные);
// 2. Преобразуем всю структуру в единую JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ОбщиеДанные);
ТелоЗапросаJSON = ЗаписьJSON.Закрыть();
// 3. Настраиваем и отправляем запрос
HTTPСоединение = Новый HTTPСоединение("example.com");
ЗапросHTTP = Новый HTTPЗапрос("/api/post");
// Устанавливаем заголовок для JSON
ЗапросHTTP.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");
// Устанавливаем тело, которое является валидной JSON-строкой
ЗапросHTTP.УстановитьТелоИзСтроки(ТелоЗапросаJSON, КодировкаТекста.UTF8);
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(ЗапросHTTP);
// ... дальнейшая обработка ответа
Content-Type должен точно соответствовать формату данных в теле запроса.ЗаписьJSON и функцию ЗаписатьJSON — это гарантирует синтаксически правильный результат.Следуя этим простым правилам, вы сможете избежать многих часов отладки и успешно настроить интеграцию 1С с любыми внешними сервисами.