При интеграции систем на платформе 1С:Предприятие 8 с внешними приложениями или при организации обмена между базами разработчики часто выбирают HTTP-сервисы. Это современный, легкий и быстрый механизм. Однако на этапе отладки многие сталкиваются с классической проблемой: запрос к сервису возвращает код состояния 404 Not Found. Особенно часто это происходит при отправке POST-запросов, в то время как GET-запросы по схожим адресам могут успешно работать.
В этой статье мы подробно разберем, почему возникает эта ошибка, как устроена маршрутизация запросов в 1С, и как правильно спроектировать HTTP-сервис для бесперебойной передачи данных в формате JSON.
Рассмотрим сценарий, с которым столкнулся автор темы. На стороне клиента выполняется следующий код для отправки POST-запроса:
Соединение = Новый HTTPСоединение("localhost", , "Admin", "1");
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
Структура = Новый Структура;
Структура.Вставить("Поле1", "Значение1");
Структура.Вставить("Поле2", "Значение2");
Структура.Вставить("Поле3", "Значение3");
ЗаписатьJSON(ЗаписьJSON, Структура);
СериализованнаяСтрока = ЗаписьJSON.Закрыть();
Запрос = Новый HTTPЗапрос("/BASE_KA_VNEDRENIE_RENAT/hs/Files");
Запрос.УстановитьТелоИзСтроки(СериализованнаяСтрока);
Результат = Соединение.ВызватьHTTPМетод("POST", Запрос);
Сообщить("Нам вернули код " + Результат.КодСостояния);
При попытке отправить этот запрос на адрес /BASE_KA_VNEDRENIE_RENAT/hs/Files система возвращает ошибку 404. При этом, если изменить адрес запроса на /BASE_KA_VNEDRENIE_RENAT/hs/Files/444, запрос успешно обрабатывается и возвращает код 200 OK.
Выясним причину такого поведения. Всё дело в настройке Шаблона URL в свойствах HTTP-сервиса внутри конфигуратора. Автор указал шаблон URL как /{File}. Для платформы 1С это означает следующее:
{File}) является обязательным параметром URL./Files/444), диспетчер маршрутов 1С успешно сопоставляет запрос с шаблоном /{File} и передает управление соответствующему методу, помещая значение "444" в параметры запроса./Files (без указания конкретного файла), то платформа считает, что данный URL не соответствует шаблону /{File}. Поскольку других шаблонов в сервисе не зарегистрировано, веб-сервер возвращает стандартную ошибку 404 (Ресурс не найден).---
Чтобы ваш HTTP-сервис корректно обрабатывал как запросы к коллекции ресурсов (например, создание нового файла через POST), так и запросы к конкретным элементам (получение файла по его идентификатору), необходимо спроектировать правильную структуру шаблонов URL. Рассмотрим, как это сделать по шагам.
Шаг 1. Разделение шаблонов в Конфигураторе
Внутри вашего HTTP-сервиса в ветке метаданных создайте два разных шаблона URL:
/ или /Files (в зависимости от корневого пути вашего сервиса).POST (для создания новых записей) и метод GET (для получения списка файлов)./{File}.GET (получить конкретный файл), PUT или POST (обновить данные), DELETE (удалить).Благодаря такому разделению, запрос к /hs/Files будет перенаправлен на первый шаблон (создание ресурса), а запрос к /hs/Files/444 — на второй (работа с конкретным элементом).
---
Проанализируем, как должен выглядеть код обработчика POST-метода на стороне 1С. Нам нужно прочитать тело запроса, которое содержит сериализованную строку JSON, и преобразовать его обратно в структуру или соответствие 1С. Для этого лучше всего использовать чтение потока:
Функция ОбработатьФайлPOST(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
// Получаем тело запроса в виде потока
ПотокДанных = Запрос.ПолучитьТелоКакПоток();
// Настраиваем чтение JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьПоток(ПотокДанных);
Попытка
// Десериализуем JSON в структуру 1С
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Здесь выполняется бизнес-логика обработки полученных данных
// Например, запись в справочник или регистр сведений
ИмяФайла = Данные.Поле1;
// Формируем успешный ответ
СтруктураОтвета = Новый Структура("Успешно", Истина);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураОтвета);
Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Исключение
// В случае ошибки парсинга возвращаем код 400 Bad Request
Ответ.КодСостояния = 400;
Ответ.УстановитьТелоИзСтроки("Ошибка обработки JSON: " + ОписаниеОшибки());
КонецПопытки;
Возврат Ответ;
КонецФункции
---
При отправке данных в формате JSON на HTTP-сервис крайне важно правильно заполнять HTTP-заголовки запроса. По умолчанию веб-сервер или платформа 1С на принимающей стороне могут некорректно интерпретировать кодировку или тип содержимого, если они не указаны явно.
Рассмотрим доработанный и правильный вариант отправки POST-запроса:
// 1. Создаем соединение
Соединение = Новый HTTPСоединение("localhost", , "Admin", "1");
// 2. Сериализуем данные в JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
Структура = Новый Структура;
Структура.Вставить("Поле1", "Значение1");
Структура.Вставить("Поле2", "Значение2");
ЗаписатьJSON(ЗаписьJSON, Структура);
СериализованнаяСтрока = ЗаписьJSON.Закрыть();
// 3. Формируем заголовки запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Заголовки.Вставить("Accept", "application/json");
// 4. Инициализируем запрос по правильному URL (без лишних параметров в конце)
Запрос = Новый HTTPЗапрос("/BASE_KA_VNEDRENIE_RENAT/hs/Files", Заголовки);
// 5. Устанавливаем тело запроса. Важно отключить BOM (Byte Order Mark),
// так как маркеры последовательности байтов могут ломать парсеры JSON на веб-серверах!
Запрос.УстановитьТелоИзСтроки(СериализованнаяСтрока, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// 6. Отправляем запрос и получаем ответ
Результат = Соединение.ВызватьHTTPМетод("POST", Запрос);
Сообщить("Код состояния ответа: " + Результат.КодСостояния);
Сообщить("Тело ответа: " + Результат.ПолучитьТелоКакСтроку());
---
Даже если ваш программный код написан абсолютно верно, а шаблоны настроены корректно, вы всё равно можете получать ошибку 404. Это связано с особенностями публикации баз 1С на веб-серверах. Обратите внимание на следующие моменты:
default.vrd (он находится в каталоге публикации на веб-сервере) и убедитесь, что в теге <httpServices> взведен флаг автоматического импорта из расширений:
<httpServices publishByDefault="true" publishExtensionsByDefault="true" />
World Wide Web Publishing Service для IIS или Apache2.4).
---
В сообщениях темы (в частности, в сообщении 9) прозвучало мнение, что для обменов между базами «1С-1С» лучше и проще использовать стандартные Web-сервисы (SOAP). Проанализируем это утверждение.
Преимущества Web-сервисов (SOAP) в 1С:
Преимущества HTTP-сервисов (REST) в 1С:
Поэтому, если планируется интеграция исключительно внутри закрытого контура "1С-1С", использование Web-сервисов действительно может сэкономить время разработчика. Однако во всех остальных случаях (интеграция с внешним миром, сайтами, мобильными клиентами) стандартом де-факто являются именно HTTP-сервисы с JSON.