Как отправить длинную JSON-строку в 1С и избежать ошибки 414?

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

При интеграции систем часто возникает ситуация, когда необходимо передать большой объем данных в формате JSON через HTTP-сервис. Начинающие разработчики часто сталкиваются с ошибкой HTTP Error 414. The request URL is too long. В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем типичные ошибки при попытке её решения и составим правильный алгоритм отправки данных.

Почему возникает ошибка 414?

Ошибка 414 означает, что строка запроса (URL) слишком длинная для того, чтобы веб-сервер мог её обработать. Рассмотрим ситуацию: когда мы используем метод GET или передаем данные через параметры в URL (все, что идет после знака вопроса ?), веб-серверы (такие как IIS или Apache) накладывают жесткие лимиты на длину этой строки. Обычно это ограничение составляет от 2048 до 8192 символов. JSON-строка с данными документа или списком товаров легко может превысить этот предел.

Важный вывод: никогда не передавайте JSON-данные через параметры URL. Для передачи структурированных данных большого объема необходимо использовать тело запроса (метод POST или PATCH).

Разбор типичных ошибок при переходе на POST-запрос

Рассмотрим ситуацию, с которой столкнулся автор темы. Попытка перевести код на использование тела запроса часто сопровождается следующими заблуждениями:

  1. Многократный вызов метода УстановитьТелоИзСтроки. Проанализируем код:
    
    тHTTPЗапрос.УстановитьТелоИзСтроки("Doc_main_data="+вхДанныеДляОтправки.ОсновныеДанныеДокументаJSON);
    тHTTPЗапрос.УстановитьТелоИзСтроки("&ECC_Obligations_List="+вхДанныеДляОтправки.СписокЭКРОбязJSON);
    
    Каждый вызов метода УстановитьТелоИзСтроки полностью перезаписывает содержимое тела запроса. В итоге на сервер уйдет только последний фрагмент данных.
  2. Неправильный Content-Type. При использовании application/x-www-form-urlencoded данные должны быть закодированы специальным образом (URL-encoding). Если просто вставить JSON, содержащий кавычки, пробелы и фигурные скобки, сервер может не понять структуру данных.
  3. Чтение данных на стороне сервера. Если данные отправлены в теле запроса, они не попадут в коллекцию Запрос.ПараметрыЗапроса. Попытка вызвать Запрос.ПараметрыЗапроса.Получить("Doc_main_data") вернет Неопределено.

Правильный способ отправки длинной JSON-строки

Выясним, как правильно сформировать запрос на стороне клиента. Лучшей практикой является использование типа контента application/json. В этом случае мы не придумываем имена переменных в строке, а отправляем «чистый» JSON-объект.

Рассмотрим пошагово реализацию на стороне отправителя:


// 1. Создаем структуру данных, которую хотим отправить
ДанныеДляОтправки = Новый Структура;
ДанныеДляОтправки.Вставить("ОсновныеДанные", вхДанныеДляОтправки.ОсновныеДанныеДокументаJSON);
ДанныеДляОтправки.Вставить("СписокОбязательств", вхДанныеДляОтправки.СписокЭКРОбязJSON);

// 2. Сериализуем структуру в одну общую JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
СтрокаJSON = ЗаписьJSON.Закрыть();

// 3. Формируем соединение и запрос
тСоединение = Новый HTTPСоединение("myfoods.kz", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
тHTTPЗапрос = Новый HTTPЗапрос("/BIS/hs/InDocSinh");

// 4. Устанавливаем заголовок Content-Type
тHTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

// 5. Устанавливаем тело запроса ОДНИМ вызовом
// Важно: ByteOrderMark.НеИспользовать критичен для многих парсеров
тHTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

// 6. Отправляем запрос
тHTTPОтвет = тСоединение.ОтправитьДляОбработки(тHTTPЗапрос);

Обработка данных в HTTP-сервисе 1С (на стороне сервера)

Теперь разберем, как принять эти данные. Поскольку мы отправили данные в теле запроса методом POST, нам нужно извлечь их из потока тела.

Посмотрим на пример кода внутри метода HTTP-сервиса:


Функция InDocSinhPost(Запрос)
    
    // Получаем тело запроса как строку
    СтрокаJSON = Запрос.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
    
    Если ПустаяСтрока(СтрокаJSON) Тогда
        Возврат Новый HTTPСервисОтвет(400); // Bad Request
    КонецЕсли;
    
    // Десериализуем JSON
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    
    Данные = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    // Теперь данные доступны как свойства структуры
    ОсновныеДанные = Данные.ОсновныеДанные;
    СписокОбязательств = Данные.СписокОбязательств;
    
    // ... логика обработки данных ...
    
    Возврат Новый HTTPСервисОтвет(200);
КонецФункции

Работа с экстремально большими объемами данных

Если ваша JSON-строка занимает десятки или сотни мегабайт, хранение её целиком в оперативной памяти в виде переменной Строка может привести к ошибке нехватки памяти (Out of Memory). В этом случае проанализируем возможность работы через файлы.

На стороне отправителя: вместо УстановитьТелоИзСтроки используем УстановитьТелоИзФайла. 1С будет передавать данные в поток постепенно, не загружая их целиком в ОЗУ.


ИмяФайлаТела = ПолучитьИмяВременногоФайла("json");
// ... код записи данных в файл через ЗаписьJSON ...
тHTTPЗапрос.УстановитьТелоИзФайла(ИмяФайлаТела);

На стороне получателя: вместо ПолучитьТелоКакСтроку() используйте метод Запрос.ПолучитьТелоКакПоток(). Это позволит обрабатывать данные «на лету» через ЧтениеJSON.ОткрытьПоток(Поток).

Настройка веб-сервера

Если даже при использовании POST вы получаете ошибку 413 (Request Entity Too Large), это означает, что сработало ограничение веб-сервера на размер тела сообщения.

Таким образом, для успешной передачи длинных JSON-строк необходимо: использовать метод POST, передавать данные в теле запроса (желательно с типом application/json), избегать многократной перезаписи тела и корректно извлекать данные на сервере через чтение тела, а не через параметры запроса.

← На главную