Свой REST API на базе 1С: от шаблона URL до рабочего запроса

· 10 мин

Содержание

Чтобы запустить HTTP-сервис в 1С 8.3, нужны три шага: создать объект в ветке Общие → HTTP-сервисы Конфигуратора и написать обработчик, опубликовать базу на веб-сервере (Apache или IIS) с включёнными HTTP-сервисами и обратиться к адресу вида http://сервер/база/hs/корневой_URL/шаблон. Без публикации на веб-сервере сервис работать не будет: сама платформа порты для внешних клиентов не открывает.

Выбор веб-сервера зависит от инфраструктуры. На Windows с готовым IIS проще остаться на нём. Для Linux и для серверов, смотрящих в интернет, обычно берут Apache 2.4, а снаружи ставят Nginx с TLS. Для разработки и тестов хватит автономного сервера ibsrv без всякого веб-сервера.

Что даёт HTTP-сервис и когда он лучше веб-сервиса

HTTP-сервис — это объект конфигурации, который принимает обычные HTTP-запросы и возвращает ответ, собранный кодом на встроенном языке. Он появился в платформе 8.3.5. По сути, это способ сделать из базы 1С REST API.

Чем он отличается от других способов интеграции:

СпособФормат обменаКогда выбирают
HTTP-сервисЛюбой: JSON, XML, файл, текстСайт, мобильное приложение, бот, вебхуки — нужен свой простой API
Веб-сервис (SOAP)XML по WSDLПартнёр требует SOAP, есть готовая WSDL-схема
OData (стандартный интерфейс)JSON/Atom по протоколу ODataНужно читать и писать объекты базы без программирования
COM-соединениеОбъекты 1С напрямуюОбмен внутри одной Windows-сети, скрипты на сервере

Сильные стороны HTTP-сервиса:

  • 🔹 вы сами решаете, какие URL, методы и поля отдать наружу;
  • 🔹 клиенту не нужны библиотеки 1С: подойдёт curl, Python, JavaScript, PHP;
  • 🔹 легко принимать вебхуки от платёжных систем, маркетплейсов и CRM;
  • 🔹 бизнес-логика остаётся в 1С, а не дублируется в интеграции.

Цена свободы — всё нужно описать самому: формат ответа, коды ошибок, проверку входных данных.

Создание HTTP-сервиса в Конфигураторе

Работать удобнее в расширении конфигурации, если база типовая и на поддержке. Тогда обновления не затрут ваш API. Если конфигурация собственная, добавляйте объект прямо в неё.

Шаг 1. Объект и корневой URL

  1. Откройте Конфигуратор, дерево конфигурации, ветку Общие → HTTP-сервисы.
  2. Добавьте новый элемент, задайте имя, например API.
  3. В свойствах укажите Корневой URL: api. Это часть адреса после /hs/.

Там же находятся свойства Повторное использование сеансов и Время жизни сеанса. К ним вернёмся в разделе про производительность.

Шаг 2. Шаблон URL и методы

Шаблон описывает путь внутри сервиса. Переменные части берутся в фигурные скобки:

  • /stock/{article} — остаток по артикулу;
  • /orders — список заказов или создание нового;
  • /orders/{id} — один заказ.

Внутри шаблона добавьте методы и выберите HTTP-метод: GET, POST, PUT, DELETE и другие. Для каждого метода задайте процедуру-обработчик. Платформа предложит имя вида StockGET и создаст функцию в модуле сервиса.

Шаг 3. Код обработчика

Обработчик получает объект HTTPСервисЗапрос и обязан вернуть HTTPСервисОтвет. Пример для GET /stock/{article}, который ищет товар по артикулу и отдаёт JSON:

Функция StockGET(Запрос)

    Артикул = Запрос.ПараметрыURL.Получить("article");

    Запрос1С = Новый Запрос;
    Запрос1С.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Номенклатура.Наименование КАК Наименование
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Артикул = &Артикул
    |    И НЕ Номенклатура.ПометкаУдаления";
    Запрос1С.УстановитьПараметр("Артикул", Артикул);
    Выборка = Запрос1С.Выполнить().Выбрать();

    Если Не Выборка.Следующий() Тогда
        Возврат ОтветJSON(404, Новый Структура("error", "Товар не найден"));
    КонецЕсли;

    Данные = Новый Структура;
    Данные.Вставить("article", Артикул);
    Данные.Вставить("name", Выборка.Наименование);
    Возврат ОтветJSON(200, Данные);

КонецФункции

Функция ОтветJSON(КодСостояния, Данные)

    Запись = Новый ЗаписьJSON;
    Запись.УстановитьСтроку();
    ЗаписатьJSON(Запись, Данные);
    Текст = Запись.Закрыть();

    Ответ = Новый HTTPСервисОтвет(КодСостояния);
    Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    Ответ.УстановитьТелоИзСтроки(Текст, КодировкаТекста.UTF8);
    Возврат Ответ;

КонецФункции

Тело POST-запроса читают так:

Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
Входные = ПрочитатьJSON(Чтение);
Чтение.Закрыть();

Что ещё есть у объекта запроса:

  • Запрос.HTTPМетод — метод, если один обработчик обслуживает несколько;
  • Запрос.ПараметрыЗапроса — параметры после ?, например ?limit=50;
  • Запрос.Заголовки — заголовки, включая ваш собственный токен;
  • Запрос.ПолучитьТелоКакДвоичныеДанные() — для файлов.

Заворачивайте основной код в Попытка … Исключение и возвращайте 500 с понятным текстом. Иначе клиент получит голую ошибку веб-расширения, а вы — пустой журнал.

Публикация базы: Apache, IIS, Nginx и автономный сервер

Сравнение вариантов:

ВариантПлатформа ОСКогда подходитНюанс
Apache 2.4Windows, LinuxОсновной выбор для продакшенаРазрядность Apache и модуля 1С должна совпадать
IISWindows ServerУже есть IIS, домен WindowsНужны компоненты ISAPI и CGI
NginxLinux, WindowsТолько как прокси перед Apache или IISМодуля 1С для Nginx нет
Автономный сервер ibsrvWindows, LinuxРазработка, тесты, небольшие файловые базыПоявился в 8.3.14, без кластера

На компьютере, где стоит веб-сервер, должны быть установлены модули расширения веб-сервера той же версии, что и платформа. Их выбирают при установке платформы.

Публикация из Конфигуратора

  1. Запустите Конфигуратор от имени администратора ОС.
  2. Откройте Администрирование → Публикация на веб-сервере.
  3. Задайте Имя публикации, например trade. Оно станет частью адреса.
  4. Выберите веб-сервер и каталог публикации.
  5. На вкладке HTTP-сервисов отметьте флажок публикации по умолчанию или выберите нужные сервисы по одному.
  6. Нажмите Опубликовать. Для Apache согласитесь на перезапуск.

Готовый адрес: http://имя-сервера/trade/hs/api/stock/A-100.

Публикация утилитой webinst

На сервере без графического Конфигуратора удобнее командная строка. Утилита лежит в каталоге bin платформы:

webinst -publish -apache24 -wsdir trade -dir "C:\www\trade" -connstr "Srvr=srv1c;Ref=trade;" -confpath "C:\Apache24\conf\httpd.conf"

Для IIS вместо -apache24 и -confpath укажите -iis. Утилита создаёт в каталоге публикации файл default.vrd. Именно он определяет, какие сервисы видны снаружи:

<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
       base="/trade" ib="Srvr=srv1c;Ref=trade;">
  <httpServices publishByDefault="false">
    <service name="API" rootUrl="api" enable="true"
             reuseSessions="autouse" sessionMaxAge="20"
             poolSize="10" poolTimeout="5"/>
  </httpServices>
</point>

После правки default.vrd перезапустите веб-сервер, иначе изменения не подхватятся. Перезапуск оборвёт текущие запросы через веб-клиент и сервисы, поэтому делайте его в спокойное время.

Nginx перед Apache

Nginx удобно ставить на внешний контур: он принимает HTTPS, держит сертификат и передаёт запрос Apache на внутренний порт:

location /trade/hs/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_read_timeout 300s;
}

Публикуйте наружу только путь /hs/, а не всю базу целиком. Тогда веб-клиент и OData останутся недоступны из интернета.

Авторизация и защита API

По умолчанию HTTP-сервис требует аутентификацию пользователем 1С. Клиент передаёт заголовок Authorization: Basic … с логином и паролем в Base64. Учётную запись лучше завести отдельную, например api_site, с ролью только на нужные данные.

Варианты доступа:

  • 🔐 Basic-авторизация пользователем 1С — стандартный путь, работает сразу;
  • 🔐 аутентификация ОС — для клиентов внутри домена Windows;
  • 🔐 логин и пароль в строке соединения default.vrd (Usr=…;Pwd=…) — все запросы идут под одним пользователем без авторизации со стороны клиента.

Третий вариант открывает сервис любому, кто знает адрес. Используйте его только с собственной проверкой: токен в заголовке, который обработчик сверяет с константой или регистром сведений, и белый список IP на Nginx.

Минимальный набор защиты для сервиса в интернете:

  1. Только HTTPS. Basic-авторизация по открытому HTTP передаёт пароль почти открытым текстом.
  2. У технического пользователя нет интерактивных ролей и права администрирования.
  3. Обработчик проверяет входные данные: тип, длину, допустимые значения.
  4. Привилегированный режим включайте точечно и только там, где без него не обойтись.
  5. На Nginx задан лимит частоты запросов (limit_req), чтобы один клиент не положил базу.

Проверка и отладка HTTP-сервиса

Сначала проверьте сервис снаружи. Для этого хватит curl:

curl -u api_site:пароль "http://srv/trade/hs/api/stock/A-100"
curl -u api_site:пароль -X POST -H "Content-Type: application/json" -d "{\"number\":\"123\"}" "http://srv/trade/hs/api/orders"

Удобнее работать в Postman или Insomnia: там сохраняются запросы, заголовки и история ответов.

Отладка обработчика по шагам

Код HTTP-сервиса выполняется на сервере, поэтому точки останова в нём ловятся только при отладке по протоколу HTTP:

  1. Переключите Конфигуратор на отладку по протоколу HTTP: параметр задают в окне Сервис → Параметры. Сервер отладки dbgs по умолчанию слушает порт 1550.
  2. В default.vrd добавьте строку <debug enable="true" protocol="http" url="http://localhost:1550"/> и перезапустите веб-сервер.
  3. В Конфигураторе откройте Отладка → Подключение и включите автоматическое подключение для HTTP-сервисов.
  4. Поставьте точку останова в обработчике и отправьте запрос из Postman.

На рабочем сервере отладку после проверки выключите. Пока строка debug активна, каждый запрос тормозит, а при остановке на точке клиент висит до таймаута.

Если отладчик подключить нельзя, пишите в журнал регистрации через ЗаписьЖурналаРегистрации() с отдельным событием, например API.Ошибка. Потом журнал легко отфильтровать по этому событию.

Диагностика: выберите симптом

Скорость и нагрузка: сеансы, лицензии, тяжёлые запросы

Каждый запрос к HTTP-сервису работает в сеансе 1С. Открыть сеанс — дорого: платформа инициализирует параметры сеанса и выполняет код при начале работы. Поэтому главный рычаг скорости — свойство Повторное использование сеансов:

ЗначениеКак работаетКогда ставить
Не использоватьНовый сеанс на каждый запросРедкие обращения, отладка
Автоматически использоватьПлатформа держит пул сеансов и раздаёт их запросамБольшинство API с частыми вызовами
ИспользоватьКлиент сам держит сеанс через cookieКлиент умеет хранить cookie и делает серию запросов

Параметры пула в default.vrd: poolSize — сколько сеансов держать, poolTimeout — сколько секунд ждать свободный сеанс. sessionMaxAge задаёт время жизни сеанса без запросов.

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

Что ещё ускоряет сервис:

  • ⚡ отдавайте данные порциями: параметры limit и offset в адресе вместо выгрузки всего справочника;
  • ⚡ в запросах выбирайте только нужные поля, без ВЫБРАТЬ *;
  • ⚡ тяжёлую обработку входящих вебхуков переносите в фоновое задание: сервис сохраняет данные в регистр и сразу отвечает 202;
  • ⚡ на клиент-серверной базе следите за долгими запросами в технологическом журнале.

Платёжные системы и маркетплейсы часто повторяют вебхук, если не получили ответ за несколько секунд. Быстрый ответ 200 или 202 и разбор в фоне спасают от задвоения документов.

Реальные сценарии: сайт, бот, вебхуки

Несколько задач, которые закрывают HTTP-сервисом чаще всего.

Остатки и цены для интернет-магазина. GET /stock?updated_since=… отдаёт только изменившиеся позиции. Сайт опрашивает его раз в 5–15 минут. Полную выгрузку делают ночью.

Приём заказов с сайта. POST /orders принимает JSON, проверяет контрагента по ИНН или телефону и создаёт заказ покупателя. В ответ — номер документа и код 201. Повторная отправка того же заказа не должна создавать дубль: храните внешний номер заказа и проверяйте его перед записью.

Телеграм-бот для менеджеров. Бот на Python обращается к GET /debts/{inn} и показывает задолженность клиента. 1С ничего не знает о Телеграме, она отвечает только на HTTP-запрос.

Вебхуки банка и платёжного сервиса. Сервис принимает уведомление об оплате, сохраняет его и ставит в очередь. Фоновое задание раз в минуту разносит оплаты по заказам.

Мобильное приложение склада. Сборщик сканирует штрихкод, приложение запрашивает GET /goods/{barcode} и получает товар, ячейку и количество к сбору.

Перед запуском API в продакшен
Выполнено: 0 / 7

Частые вопросы

Можно ли запустить HTTP-сервис на файловой базе?
Да. Файловую базу публикуют на Apache или IIS так же, как серверную, указывая в строке соединения File="путь". Для серьёзной нагрузки лучше клиент-серверный вариант.
Как вернуть файл, а не JSON?
Заполните тело через УстановитьТелоИзДвоичныхДанных() и укажите заголовки Content-Type и Content-Disposition с именем файла.
Почему изменения в коде обработчика не видны клиенту?
Конфигурацию базы данных не обновили или веб-сервер держит старые сеансы из пула. Обновите конфигурацию базы данных и перезапустите веб-сервер в нерабочее время.
Как сделать версионирование API?
Заведите два сервиса с корневыми URL api_v1 и api_v2 или добавьте версию в шаблон: /v1/orders. Старую версию держите, пока все клиенты не перейдут.
Чем HTTP-сервис отличается от стандартного интерфейса OData?
OData отдаёт объекты базы как есть, без кода. HTTP-сервис отдаёт то, что вы запрограммировали: свой формат, проверки и бизнес-логику.