rest · REST API 26.1300.0 Ломающее

Rest 26.1200.0–26.1300.0: строгие типы REST V3 и лимит времени SQL

8 мин чтения Устаревших API: 2
Узнавайте о ломающих изменениях Битрикса раньше, чем они доедут до прода: свежие разборы — в канале @bxmax_updates

Ломающее обновление

Удалены или изменены публичные API — прикладной код может перестать работать.

Две версии Rest подряд закручивают гайки. В 26.1200.0 REST V3 перестал прощать "42" вместо 42, а права приложений переехали из ORM-поля в отдельную таблицу. В 26.1300.0 появился лимит времени SQL для REST-вызовов, исчез старый LoadLimiter, а параметры встраивания ограничены 2048 байтами. Если у вас интеграции на V3 или код, который читает AppTable, прогоните их на тестовом портале до обновления.

Новое

Ограничьте долгие SQL-запросы REST

В 26.1300.0 у модуля появились две опции. sql_query_time_limit_active включает лимит для старого REST и V3, по умолчанию он выключен. sql_query_time_limit задаёт секунды: по умолчанию 30, ноль снимает ограничение. Работает на MySQL от 5.7.8 и MariaDB от 10.1.1.

        use Bitrix\Main\Config\Option;

Option::set('rest', 'sql_query_time_limit_active', 'Y');
Option::set('rest', 'sql_query_time_limit', '10');

    

Лимит ставится на SQL-сессию только на время вызова, потом возвращается DEFAULT. Общую длительность HTTP-запроса он не режет. Если запрос не уложился, клиент получит HTTP 503 с Retry-After, равным заданному числу секунд. Клиенту стоит уважать этот заголовок:

        const response = await fetch(url, { method: 'POST', body });
if (response.status === 503) {
    const delay = Number(response.headers.get('Retry-After') ?? 30);
    await new Promise((resolve) => setTimeout(resolve, delay * 1000));
    // повторить запрос
}

    

При ограничении нагрузки V3 тоже отдаёт Retry-After: оставшееся время блокировки в Redis или 300 секунд. На ответы 429 старого REST этот заголовок приходит не всегда.

Разрешите сотрудникам управлять своими встраиваниями

С 26.1200.0 в настройках REST есть политика ManageOwnEmbeddings. Личное приложение проходит три проверки: владелец, эта политика и доступ к приложению. Локальному нужны право создания и доступ. Администратора политика не ограничивает, обработчики placement тоже учитывают владельца и права приложения. В 26.1300.0 сотрудник без прав администратора может редактировать свою интеграцию, если проходит проверки доступа и preset не закрыт для всех, кроме администраторов.

Из кода политику сохраняет Bitrix\Rest\Public\Command\Embedding\AccessPolicy\SetOwnEmbeddingAccessCommand, читает AccessPolicyProvider::getAccessCodesAllowedToManageOwnEmbeddings(). Ошибка POLICY_AUDIT_FAILED значит, что политика сохранена, но запись в аудит не удалась: повторять сохранение не нужно.

Посчитайте лимиты batch заново

С 26.1200.0 ограничитель нагрузки считает legacy-batch одним вызовом: вложенные запросы больше не тратят лимит по отдельности и не возвращают свои сведения о нём. time.operating_reset_at теперь считается по границе окна учёта, при активной блокировке он, как и раньше, показывает её окончание.

В 26.1300.0 подстановки batch внутри fields и правых частей filter приводятся к типам DTO, включая вложенные структуры. Строка "42" станет int, если обратное преобразование даёт ту же строку. "042", -0 и числа за пределами int остаются строками. Обычных JSON-значений это не касается, их по-прежнему нужно передавать в правильном типе.

Меню приложений и локальная сеть

MenuApplicationProvider::getForWeb() и getForMobile() в 26.1200.0 отдают доступные пользователю приложения с локализованными названиями, мобильный список требует MOBILE=Y. В списке установленных приложений права пользователя проверяются до пагинации. В 26.1300.0 iframe приложения получил разрешения локальной сети для своего origin: в Chrome 142 и новее приложение может обращаться к устройствам локальной сети, если это разрешил браузер.

Что сломается

Передавайте в REST V3 значения правильного типа

С 26.1200.0 int-поле в fields отклоняет строку "42" и дробное число. String принимает только строку, bool только true/false (не 0/1), float принимает float и int. Несуществующая дата 2026-02-31 больше не превращается в 3 марта. Чаще всего ломается код, который отдаёт в API строки из $row как есть:

        $fields = [
    'id'     => (int) $row['ID'],
    'active' => $row['ACTIVE'] === 'Y',
    'price'  => (float) $row['PRICE'],
    'title'  => (string) $row['TITLE'],
];

    

У int-параметров самого запроса своя проверка: она отклоняет boolean, дробные числа, нецелые числовые строки и float больше 2**53.

Права из grant теперь проверяются в filter, order, fields, cursor и агрегатном select. Пустой select: [] больше не обходит scope, а запрещённые поля верхнего уровня вырезаются из ответа, id остаётся. Если интеграция получала поле, на которое у неё нет права, после обновления она его не увидит. В 26.1300.0 ту же проверку пустого select распространили на нестандартные структуры, кроме агрегатной.

Замените обращения к PHP API

У Bitrix\Rest\AppTable с 26.1200.0 нет ORM-поля ACCESS, запросы с ним и ORM-геттер getAccess() падают. Права приложения по-прежнему отдаёт getByClientId():

        use Bitrix\Rest\AppTable;

$app = AppTable::getByClientId($clientId);
$access = $app['ACCESS'] ?? null;

    

Записывает их AppTable::setAccess($appId, $rights).

AddEmbeddingCommandHandler::__invoke() из Bitrix\Rest\Public\Command\Application\Embedding при ошибке placement.bind с 26.1200.0 бросает Bitrix\Rest\RestException вместо PersistenceException. Старый catch (PersistenceException) его не поймает.

В 26.1300.0 удалён Bitrix\Rest\Engine\Access\LoadLimiter, алиаса нет. Новый Bitrix\Rest\V3\Limiter\LoadLimiter работает через объект с методами check, start, finish и зависимостями в конструкторе, а цепочку лимитеров собирает LimiterChainFactory. Заменой namespace статические вызовы не спасти, код придётся переписать.

Проверьте встраивания и установку приложений

С 26.1300.0 placement.bind и запись PlacementTable.OPTIONS отклоняют JSON длиннее 2048 байт. Ядро меряет strlen(Json::encode($options, 0)), хотя в тексте ошибки написано characters. Без флага JSON_UNESCAPED_UNICODE каждая кириллическая буква превращается в \uXXXX и занимает шесть байт, так что русские подписи упираются в лимит примерно на 340 символах. Проверить заранее можно тем же методом, которым пользуется ядро:

        use Bitrix\Rest\PlacementTable;

$check = PlacementTable::validateOptionsLength($options);
if ($check !== true) {
    throw new \LengthException($check);
}

    

У собственных V3-контроллеров автоматические маршруты <resource>.field.custom.list/get/delete/update/add теперь создаются, только если в #[FieldAccess] DTO указан провайдер доступа. Обычные .field.list/get и явно объявленные маршруты остаются.

Marketplace\Application::install() получил шестой аргумент bool $createSystemUser = false. Чтобы новая или неактивная установка могла создать системного пользователя, передайте true при включённой опции allow_create_sys_user:

        use Bitrix\Rest\Marketplace\Application;

$result = Application::install($code, createSystemUser: true);

    

Старый вызов без аргумента получит отказ. У уже активного приложения решение не перезаписывается, а если атрибута нет, при включённой общей опции действует прежнее разрешение.

user.update в 26.1300.0 отклоняет массивы и неподходящие объекты в строковых полях, принимает scalar, null и Stringable, файловые PERSONAL_PHOTO и WORK_LOGO проверка не трогает. В MESSAGE_ID при подтверждении offline-событий допустимы только scalar-элементы массива, null нельзя. Описание шага в конструкторе форм выводится текстом: если вы вставляли туда HTML, он покажется как разметка.

БД

С 26.1200.0 права приложений лежат в b_rest_app_access: ID, APP_ID, ACCESS_CODE varchar(100), уникальный индекс (APP_ID, ACCESS_CODE). На нашем обновлённом эталоне столбец b_rest_app.ACCESS в базе остался, но ORM его больше не описывает. Если вы читали права прямым SQL из b_rest_app, переключитесь на новую таблицу или на getByClientId().

В 26.1300.0 решение CREATE_SYSTEM_USER хранится в атрибутах приложения. Невалидный JSON в PlacementTable.OPTIONS при чтении через ORM превращается в [].

Мелочи и находки

  • В 26.1200.0 фильтр IN [] больше не генерирует SQL IN (), а структурированные фильтры проходят те же преобразования, что обычные. В 26.1300.0 ORM сохраняет имена UF_* без смены регистра.
  • MCP в 26.1200.0 проверяет поля по грамматике REST-структур и возвращает имена полей с ошибками, nullable-параметры без значения по умолчанию перестали быть обязательными. В 26.1300.0 агрегатный select описан в схеме как объект функций, hiddenFields и fieldWhitelist действуют и на агрегаты, пустые аргументы больше не подхватывают тело внешнего HTTP-запроса.
  • Импорт конфигурации в 26.1200.0 повторно проверяет доступ к выбранному манифесту и берёт MANIFEST_CODE с сервера. Локализованные названия очищаются после успешного сохранения приложения.
  • В 26.1300.0 исключение в callback при закрытии приложения из боковой панели больше не роняет страницу, оно уходит в BX.debug.

Устаревшие и удалённые API в этой версии

Символ Статус Чем заменять
Bitrix\Rest\AppTable.ACCESS Удалено Bitrix\Rest\AppTable::getByClientId() / Bitrix\Rest\AppTable::setAccess()
Bitrix\Rest\Engine\Access\LoadLimiter Удалено Bitrix\Rest\V3\Limiter\LoadLimiter

Новая версия вышла — разбор уже в Telegram

В канале @bxmax_updates публикуем каждый свежий разбор: что сломается, что устарело и что появилось в API. Узнаете до того, как обновите прод.

Подписаться

Читайте дальше

rest 26.1100.0 Ломающее Свежее

Rest 26.1000.0–26.1100.0: JSON-ответы потоком, свои права на методы полей REST 3.0 и встройки модулей в интерфейсе

В rest 26.1000.0 JSON-ответы REST пошли потоком, а модуль теперь сам решает, кому доступны методы полей REST 3.0. В 26.1100.0 встройки модулей без приложения из [разбора 26.900.0](/bitrix-updates/rest/rest-26-900-0) открываются в стандартном интерфейсе. До обновления проверьте свои точки входа REST,…

1 мин
rest 26.900.0 Заметное Свежее

Rest 26.900.0: встройки без приложения, чтение приложений без AppTable и заготовка MCP

В rest 26.900.0 у встроек появился владелец, и модуль может повесить встройку на свою сущность без REST-приложения. Приложение читается в типизированный DTO через `ApplicationProvider::find*()`, статус оплаты считает `ApplicationStatusCalculator`, а для REST 3.0 заложен мост в MCP, который в БУС не…

2 мин
rest 26.800.0 Ломающее

Rest 26.700.0–26.800.0: отложенная установка приложений, строгий bool в REST 3.0 и вебхуки со сроком действия

В БУС вышли подряд две версии `rest`: 26.700.0 и 26.800.0. В 26.700.0 у входящих вебхуков появился срок действия, а сотрудник без права установки может попросить администратора поставить приложение. В 26.800.0 поменялось время срабатывания `OnRestAppInstall`, REST 3.0 стал строже проверять входные д…

2 мин
rest 26.600.0 Ломающее

Rest 26.600.0: отложенный batch и Idempotency-Key в REST V3, новые правила для встроек

В `rest` 26.600.0 (сборка от 23.07.2026) 143 файла и +5143/−383 строк. В REST V3 появились отложенный batch со своей таблицей и очередью, идемпотентность по заголовку `Idempotency-Key` и перечисления, значения которых берутся из кода. Заодно переделали права на встройки и сигнатуры команд встроек. К…

1 мин
Мы используем файлы cookie для улучшения работы сайта. Продолжая использовать сайт, вы соглашаетесь с нашей политикой конфиденциальности.
AI Домовой

AI Домовой История

на связи

пишет…

Можно закрыть чат и перейти на другую страницу. Когда ответ будет готов, на кнопке Домового появится отметка.

Нет истории чатов
AI Домовой

Нужна авторизация

Войдите, чтобы задавать вопросы AI Домовому.

Войти