Почему HTTP-запрос из 1С возвращает ошибку 404, когда в браузере скрипт работает?

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

При интеграции 1С со сторонними веб-сервисами, сайтами или внутренними скриптами разработчики часто сталкиваются с ситуацией: в адресной строке веб-браузера запрос успешно выполняется и возвращает корректный результат, а при вызове того же адреса из программного кода 1С через объект HTTPСоединение возвращается код состояния 404 Not Found. Разберем причины такого поведения платформы и посмотрим, как правильно настроить выполнение HTTP-запросов.

Анализ проблемы и параметров конструктора HTTPСоединение

Рассмотрим исходный пример кода, вызывавший ошибку:


ИмяСервераHTTP = "188.188.188.188";
ПортHTTP = 8088;
Соединение = Новый HTTPСоединение(ИмяСервераHTTP, ПортHTTP,,,,60,);

Попытка
    ИмяВыходногоФайла = ПолучитьИмяВременногоФайла("txt");
    Запрос = Новый HTTPЗапрос;
    Запрос.АдресРесурса = "/resurs/test.php";
    Ответ = Соединение.Получить(Запрос, ИмяВыходногоФайла);
    
    Если Ответ.КодСостояния <> 200 Тогда
        Сообщить("Ошибка: " + Ответ.КодСостояния);
    Иначе
        Сообщить("Удача");
    КонецЕсли;
Исключение
    Сообщить("Ошибка запроса! " + ОписаниеОшибки());
КонецПопытки;

Проанализируем ситуацию: когда разработчик тестировал обращение в веб-браузере, он вводил адрес вида 188.188.188.188/resurs/test.php. Браузер по умолчанию отправляет запросы по стандартному порту 80 (для протокола HTTP) или 443 (для протокола HTTPS). Однако в коде 1С в параметрах конструктора HTTPСоединение был явно указан порт 8088. На этом порту либо не был настроен веб-сервер, либо на нем был развернут другой виртуальный хост, не содержащий нужного каталога и файла, из-за чего веб-сервер возвращал ответ 404.

Решение проблемы с указанием портов

Если веб-сервер принимает входящие соединения на стандартном порту, явное указание порта в конструкторе следует опустить или передать значение Неопределено. В таком случае платформа 1С автоматически подставит порт 80 (или 443, если в параметрах защиты передан объект ЗащищенноеСоединениеOpenSSL).

Посмотрим на исправленный вариант инициализации соединения:


ИмяСервераHTTP = "188.188.188.188";
// Не указываем порт явно, если используется стандартный веб-порт 80
Соединение = Новый HTTPСоединение(ИмяСервераHTTP,,,,,60);

Обратите внимание на синтаксис первого параметра: в параметр Сервер объекта HTTPСоединение передается только чистое доменное имя или IP-адрес без указания протокола (http:// или https://) и без завершающих слэшей.

Другие частые причины расхождения работы браузера и 1С

Если порт указан верно, но веб-сервер все равно возвращает код 404 или ошибку доступа, выясним другие возможные причины различий:

  1. Виртуальные хосты (Virtual Hosts) и отсутствие заголовка Host: когда обращение идет по IP-адресу, веб-сервер (Nginx, Apache, IIS) направляет запрос в дефолтный каталог. Если сайт привязан к доменному имени, сервер не найдет ресурс. В таких случаях передавайте в HTTPСоединение доменное имя либо явно добавляйте заголовок Host:
    
    Запрос = Новый HTTPЗапрос("/resurs/test.php");
    Запрос.Заголовки.Вставить("Host", "mysite.domain");
    
  2. Разница в сетевом окружении (Клиент vs Сервер): если процедура выполняется на стороне сервера 1С (в контексте &НаСервере или регламентном задании), запрос отправляется от имени самого сервера 1С, а не с пользовательского ПК. На сервере могут быть заблокированы порты брандмауэром или отсутствовать маршрут до IP-адреса.
  3. Поведение при перенаправлениях (HTTP 301/302): браузер автоматически выполняет редирект при изменении URL (например, при добавлении завершающего слэша к пути каталога). Платформа 1С не переходит по редиректам автоматически: необходимо анализировать полученный статус и при статусах 3xx считывать целевой адрес из заголовка Location ответа.
  4. Прокси-сервер: в отличие от браузера, который может автоматически считывать системные настройки прокси операционной системы, в 1С при необходимости работы через корпоративный прокси следует использовать объект ИнтернетПрокси и передавать его в конструктор соединения.

Оптимизация чтения ответа: работа в оперативной памяти

В типовых задачах интеграции сохранять ответ веб-сервера во временный файл на диске через ПолучитьИмяВременногоФайла необязательно. Вызов метода Получить() без указания имени файла сохраняет ответ в оперативной памяти, что существенно ускоряет обработку запросов и исключает лишние операции с файловой системой.

Разберем эталонный пример отправки GET-запроса и чтения ответа в строку:


ИмяСервера = "188.188.188.188";
ПутьКРесурсу = "/resurs/test.php";

// Создаем соединение с таймаутом 60 секунд
Соединение = Новый HTTPСоединение(ИмяСервера, , , , , 60);

Запрос = Новый HTTPЗапрос(ПутьКРесурсу);
Запрос.Заголовки.Вставить("Accept", "text/html,application/xhtml+xml,application/json");

Попытка
    Ответ = Соединение.Получить(Запрос);
    
    Если Ответ.КодСостояния = 200 Тогда
        // Считываем тело ответа напрямую в строку с указанием кодировки UTF-8
        ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
        Сообщить("Успешный ответ: " + ТекстОтвета);
    Иначе
        Сообщить("Ошибка HTTP: " + Строка(Ответ.КодСостояния));
        // Читаем тело ответа с подробностями об ошибке от веб-сервера
        Сообщить("Текст ошибки: " + Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
    КонецЕсли;
Исключение
    Сообщить("Сетевая ошибка при выполнении запроса: " + ОписаниеОшибки());
КонецПопытки;

Для защищенных соединений HTTPS в седьмой параметр конструктора HTTPСоединение передается объект Новый ЗащищенноеСоединениеOpenSSL(), а стандартный порт 443 также подставляется платформой автоматически.

← На главную