Как передать символ слэша в значении параметра HTTP-сервиса в 1С

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

При интеграции систем на платформе 1С с внешними веб-сервисами разработчики часто сталкиваются с необходимостью передавать сложные текстовые параметры, содержащие специальные символы. Одним из наиболее проблемных символов является обычный прямой слэш (/). Он часто встречается в номерах договоров (например, "ф1-0512/2016-1"), артикулах товаров или кодах документов.

Попытка передать такой параметр напрямую в строке URL-запроса (в качестве параметра пути или Query-параметра) неизбежно приводит к ошибкам веб-сервера вроде 404 Not Found или 400 Bad Request. В этой статье мы подробно разберем, почему возникает эта проблема, и рассмотрим несколько эффективных способов ее решения.

Почему символ слэша ломает HTTP-запросы?

Символ / является зарезервированным символом в спецификации протокола HTTP. Он используется в качестве разделителя сегментов пути (Path) в URL-адресе. Когда клиент отправляет запрос, в котором значение параметра содержит слэш, веб-сервер (будь то IIS или Apache) воспринимает его как команду перехода к новому каталогу или сегменту адреса.

Даже если мы попытаемся применить стандартное URL-кодирование (Percent-Encoding), заменив слэш на %2F, это не всегда решает проблему. По соображениям безопасности многие современные веб-серверы по умолчанию блокируют запросы, содержащие закодированные слэши в путях URL, возвращая ошибку еще до того, как запрос будет передан на обработку в базу 1С.

Давайте по шагам разберем варианты обхода этого ограничения, начиная с самого правильного и заканчивая альтернативными сценариями.

Решение 1: Перенос данных в тело POST-запроса (Рекомендуемый метод)

Самый надежный способ передачи сложных структур данных, содержащих любые спецсимволы, кириллицу или длинный текст — это полный отказ от передачи параметров в строке адреса (URL) или заголовках. Вместо этого следует использовать HTTP-метод POST (или PUT) и передавать данные в теле запроса в формате JSON.

Рассмотрим, как правильно реализовать этот подход на встроенном языке 1С.

Шаг 1. Отправка POST-запроса на стороне клиента:

Вместо формирования длинной строки URL мы создаем объект HTTPЗапрос, упаковываем наши параметры в JSON и помещаем их в тело запроса с помощью метода УстановитьТелоИзСтроки.


// Настраиваем соединение с веб-сервером
Соединение = Новый HTTPСоединение("имя_хоста_или_ip");

// Указываем относительный путь к нашему HTTP-сервису
Запрос = Новый HTTPЗапрос("/hs/MyCustomService/v1/GetContractData");

// Обязательно указываем заголовок Content-Type, чтобы сервер понял формат данных
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

// Формируем структуру с параметрами, содержащими слэш
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("ContractNumber", "ф1-0512/2016-1");
ПараметрыЗапроса.Вставить("Password", "123");

// Сериализуем структуру в JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
СтрокаТела = ЗаписьJSON.Закрыть();

// Помещаем JSON в тело запроса
Запрос.УстановитьТелоИзСтроки(СтрокаТела, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

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

Шаг 2. Получение и обработка данных на стороне HTTP-сервиса 1С:

В модуле HTTP-сервиса 1С в соответствующем методе POST мы извлекаем переданную строку и десериализуем ее обратно в структуру программных объектов.


Функция ПолучитьДанныеДоговора(Запрос)
    
    // Получаем тело запроса в виде строки UTF-8
    СтрокаJSON = Запрос.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
    
    Если ПустаяСтрока(СтрокаJSON) Тогда
        Ответ = Новый HTTPСервисОтвет(400);
        Ответ.УстановитьТелоИзСтроки("Пустое тело запроса");
        Возврат Ответ;
    КонецЕсли;
    
    // Парсим JSON
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    
    Попытка
        Данные = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
    Исключение
        ЧтениеJSON.Закрыть();
        Ответ = Новый HTTPСервисОтвет(400);
        Ответ.УстановитьТелоИзСтроки("Ошибка разбора JSON: " + ОписаниеОшибки());
        Возврат Ответ;
    КонецПопытки;
    
    // Теперь мы можем безопасно обратиться к нашему номеру со слэшем
    НомерДоговора = Данные.ContractNumber; // Получим исходное значение: "ф1-0512/2016-1"
    Пароль = Данные.Password;
    
    // Выполняем бизнес-логику...
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.УстановитьТелоИзСтроки("Данные успешно обработаны");
    Возврат Ответ;
    
КонецФункции

Решение 2: Использование URL-кодирования (Query Parameters)

Если бизнес-логика или спецификации внешнего API требуют использования исключительно метода GET, передавать слэш в параметрах пути (Path Parameters) вида /hs/service/GetContract/ф1-0512/2016-1 категорически не рекомендуется. Платформа 1С не сможет сопоставить URL с шаблоном вашего HTTP-сервиса, поскольку решит, что в адресе содержится дополнительный сегмент пути.

Вместо этого параметры необходимо передавать в секции запроса (Query Parameters) после вопросительного знака: /hs/service/GetContract?ContractNumber=значение. При этом значение параметра обязательно должно быть закодировано.

Для преобразования спецсимволов во встроенном языке 1С используется функция КодироватьСтроку с указанием способа кодирования СпособКодированияСтроки.КодировкаURL.

Проанализируем пример кодирования:


ИсходныйНомер = "ф1-0512/2016-1";
КодированныйНомер = КодироватьСтроку(ИсходныйНомер, СпособКодированияСтроки.КодировкаURL);
// Значение переменной КодированныйНомер станет: "%D1%841-0512%2F2016-1"

// Формируем безопасный GET-запрос
АдресЗапроса = "/hs/MyCustomService/v1/GetContract?ContractNumber=" + КодированныйНомер;
Запрос = Новый HTTPЗапрос(АдресЗапроса);

При получении такого запроса в HTTP-сервисе 1С платформа автоматически декодирует параметры, и в коллекции Запрос.ПараметрыЗапроса вы получите исходную строку со слэшем без дополнительных манипуляций:


НомерДоговора = Запрос.ПараметрыЗапроса.Получить("ContractNumber"); // Вернет "ф1-0512/2016-1"

Решение 3: Настройка веб-серверов для пропуска закодированных слэшей

Если вы все же используете передачу параметров со слэшем внутри URL и получаете ошибку от веб-сервера (даже при URL-кодировании), вам потребуется перенастроить веб-сервер, на котором опубликована информационная база 1С.

Для Microsoft IIS:

По умолчанию IIS блокирует символы двойного экранирования. Чтобы разрешить обработку закодированных символов, откройте файл web.config в корневом каталоге публикации вашей базы 1С и добавьте в секцию <system.webServer> следующую настройку фильтрации запросов:


<configuration>
    <system.webServer>
        <security>
            <requestFiltering allowDoubleEscaping="true" />
        </security>
    </system.webServer>
</configuration>

Для Apache:

По умолчанию веб-сервер Apache возвращает ошибку 404 при попытке использовать закодированный слэш %2F в пути запроса. Чтобы исправить это поведение, откройте конфигурационный файл Apache (httpd.conf) или файл настроек конкретного виртуального хоста и добавьте директиву:

AllowEncodedSlashes On

После внесения изменений обязательно перезапустите службу веб-сервера для применения новых настроек.

Решение 4: Кодирование параметров в формат Base64

В ситуациях, когда у вас нет доступа к конфигурационным файлам веб-сервера IIS или Apache (например, при использовании облачных хостингов), а передавать спецсимволы в URL крайне необходимо, отличным выходом станет использование кодирования в Base64.

Схема работы выглядит следующим образом:

  1. Отправитель конвертирует строку со слэшем в формат Base64. Символ / преобразуется в алфавитно-цифровой набор символов, который безопасен для любого веб-сервера.
  2. В веб-запросе передается полученная Base64-строка.
  3. HTTP-сервис 1С принимает строку, декодирует ее обратно и получает исходное значение.

Рассмотрим пример декодирования Base64 на стороне HTTP-сервиса 1С:


// Получаем переданный Base64-параметр из запроса
ПараметрBase64 = Запрос.ПараметрыЗапроса.Получить("ContractNumber"); 

Если ЗначениеЗаполнено(ПараметрBase64) Тогда
    // Декодируем Base64 в двоичные данные
    ДвоичныеДанныеДекод = Base64Значение(ПараметрBase64);
    
    // Для получения текста записываем двоичные данные во временный файл
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
    ДвоичныеДанныеДекод.Записать(ИмяВременногоФайла);
    
    // Считываем текст в кодировке UTF-8
    ЧтениеТекста = Новый ЧтениеТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
    ИсходныйНомерДоговора = ЧтениеТекста.Прочитать();
    ЧтениеТекста.Закрыть();
    
    // Удаляем временный файл за собой
    УдалитьФайлы(ИмяВременногоФайла);
КонецЕсли;

Выводы и рекомендации

Мы проанализировали различные методы передачи символа слэша в HTTP-сервисах 1С. Подведем краткий итог по выбору оптимального решения:

  1. Если объем передаваемых данных велик или структура параметров сложная — используйте метод POST и передачу данных в теле запроса в формате JSON. Это самый надежный и промышленный стандарт разработки веб-сервисов.
  2. Если вы вынуждены использовать GET-запросы — передавайте параметры через Query Parameters (после знака ?), предварительно закодировав их функцией КодироватьСтроку().
  3. Если сервер блокирует закодированные спецсимволы, примените настройки allowDoubleEscaping="true" для IIS или AllowEncodedSlashes On для Apache.
  4. В качестве быстрого "обходного" решения без перенастройки серверов используйте кодирование Base64.
← На главную