BX.ajax.runComponentAction. Аякс запросы Битрикс

Начиная с релиза Bitrix 17.5.10 появилась обновлённая реализация AJAX-взаимодействия. Платформа теперь позволяет напрямую обращаться к методам модулей или компонентов через AJAX, минуя этап рендеринга шаблона сайта. Это означает, что при обработке запроса система выполняет только необходимую служебную логику и целевую функцию, без лишних операций.

Со стороны клиента реализация достаточно проста — достаточно отправить стандартный AJAX-запрос на эндпоинт /bitrix/services/main/ajax.php. Встроенные методы JavaScript-библиотеки Bitrix существенно упрощают формирование таких запросов, предлагая более лаконичный синтаксис по сравнению с ручной настройкой вызовов.

Пример Битриксовой функции для обращения к компоненту

Приведу код и jsdoc битриксовой функции. Из jsdoc можно узнать параметры, которые эта функция ожидает:

/**
    *
    * @param {string} component
    * @param {string} action
    * @param {Object} config
    * @param {?string} [config.analyticsLabel]
    * @param {?string} [config.signedParameters]
    * @param {string} [config.method='POST']
    * @param {string} [config.mode='ajax'] Ajax or class.
    * @param {Object} [config.data]
    * @param {?array} [config.headers]
    * @param {?number} [config.timeout]
    * @param {Object} [config.navigation]
    */
BX.ajax.runComponentAction = function (component, action, config)
{
    config = prepareAjaxConfig(config);
    config.mode = config.mode || 'ajax';

    var getParameters = prepareAjaxGetParameters(config);
    getParameters.c = component;
    getParameters.action = action;

    var url = BX.util.add_url_param('/bitrix/services/main/ajax.php', getParameters);

    return buildAjaxPromiseToRestoreCsrf({
        method: config.method,
        dataType: 'json',
        url: url,
        data: config.data,
        timeout: config.timeout,
        preparePost: config.preparePost,
        headers: config.headers
    });
};

Обращение к методам компонента через AJAX (файл class.php)

Клиентская реализация

Рассмотрим компонент со следующей структурой:

  • Пространство имен (namespace): my_components

  • Компонент: ajax

  • Метод действия: testAction(), определенный в классе компонента (class.php).

Пример вызова через JS-библиотеку Bitrix: Для выполнения AJAX-запроса к методу компонента используйте метод BX.ajax.runComponentAction().

// делаем ajax запрос в компонент my_components:ajax к методу testAction()
BX.ajax.runComponentAction('my_components:ajax', 'test', {
	mode: 'class', // Это означает, что мы хотим вызывать действие из class.php, а конкретно метод test. Может принимать ajax.php - в нем автоСвязывание идет сразу под капотом.
	data: {
		person: 'Hero!' //данные будут автоматически замаплены на параметры метода
	},
	analyticsLabel: {
		viewMode: 'grid',
		filterState: 'closed'
	}
}).then(function (response) {
	console.log(response);
	/**
		 {
			"status": "success",
			"data": "Hi Hero!",
			"errors": []
		}
	 **/
}, function (response) {
	//сюда будут приходить все ответы, у которых status !== 'success'
	console.log(response);
	/**
		{
			"status": "error",
			"errors": [...]
		}
	 **/
});

Особенности:

  1. Автоматическая передача контекста: Сессия пользователя (PHPSESSID), CSRF-токен (sessid) и другие авторизационные данные передаются в заголовках запроса без явного указания.

  2. Минимальная нагрузка: Запрос направляется на эндпоинт /bitrix/services/main/ajax.php, где выполняется только служебная логика Bitrix и целевой метод компонента (без инициализации шаблона).

  3. Режим mode: 'class': Указывает на необходимость вызова метода из файла class.php (класс компонента, наследующий CBitrixComponent). Возможен еще mode: 'ajax': для обращения к ajax.php

Требования к серверной части:

  • Метод testAction() должен быть объявлен как публичный в классе компонента.

  • Для обработки AJAX-запросов корректно реализуйте проверку прав доступа и CSRF-защиту (при необходимости).

 

Обработка CSRF и настройка фильтров на серверной стороне


CSRF-защита

Для предотвращения межсайтовой подделки запросов (CSRF) в AJAX-методах:

  1. Передача токена:

    • На клиенте добавьте параметр sessid в data запроса, используя BX.message('bitrix_sessid').
    • Либо передайте токен с сервера через PHP:

      data: { sessid: '<?= bitrix_sessid() ?>' }  
  2. Отключение проверки (не рекомендуется):\ Если метод не обрабатывает критичные данные, CSRF-проверку можно отключить в конфигурации серверного действия.

Серверная реализация

Структура компонента

  • Путь к классу: /local/components/my_components/ajax/class.php
  • Метод действия: testAction (суффикс Action обязателен).
  • Аргументы метода:\ Параметры маппятся по имени из запроса, независимо от порядка объявления. Пример:

    public function testAction($param2 = 'default', $param1 = '') { ... }  

    Если клиент передает param1, он будет присвоен аргументу $param1, даже если объявлен вторым.


Настройка фильтров через configureActions()

Метод определяет пре-/постфильтры для валидации запросов.

1. Пример с фильтрами по умолчанию:

public function configureActions() {
  return [
    'test' => [
      'prefilters' => [
        new Authentication(),      // Требует авторизации
        new HttpMethod([HttpMethod::METHOD_GET, HttpMethod::METHOD_POST]), // Разрешенные HTTP-методы
        new Csrf(),                // CSRF-проверка (требует `sessid` в POST)
      ]
    ]
  ];
}  

2. Отключение фильтров:

public function configureActions() {
  return [
    'test' => [
      'prefilters' => [],  // Все стандартные фильтры игнорируются
      'postfilters' => []
    ]
  ];
}  

Важно:

  • Если метод configureActions() не переопределен, применяются стандартные фильтры:
    • Authentication
    • HttpMethod (GET/POST)
    • Csrf (для POST).

Примеры классов компонента

1. С включенными фильтрами:

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

class MyComponent extends CBitrixComponent implements \Bitrix\Main\Engine\Contract\Controllerable {
  public function configureActions() {
    return [
      'test' => [
        'prefilters' => [
          new \Bitrix\Main\Engine\ActionFilter\Authentication(),
          new \Bitrix\Main\Engine\ActionFilter\HttpMethod([
            \Bitrix\Main\Web\HttpMethod::GET,
            \Bitrix\Main\Web\HttpMethod::POST
          ]),
          new \Bitrix\Main\Engine\ActionFilter\Csrf()
        ]
      ]
    ];
  }

  public function testAction($param2 = 'default', $param1 = '') {
    return [
      'asd' => $param1,
      'count' => 200
    ];
  }
}
?>  

2. С отключенными фильтрами:

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

class MyComponent extends CBitrixComponent implements \Bitrix\Main\Engine\Contract\Controllerable {
  public function configureActions() {
    return [
      'test' => [
        'prefilters' => [], // Фильтры отключены
        'postfilters' => []
      ]
    ];
  }

  public function testAction($param2 = 'default', $param1 = '') {
    return [
      'asd' => $param1,
      'count' => 200
    ];
  }
}
?>  

Примечания:

  • Reflection API: Bitrix анализирует имена аргументов метода через Reflection, чтобы сопоставить их с параметрами запроса.
  • Типы данных: Аргументы метода автоматически приводятся к типам, указанным в объявлении (например, int $param).
  • Стандартные фильтры: Находятся в bitrix/modules/main/lib/engine/actionfilter/.

Обращение к компонентам через файл ajax.php и работа с модулями


AJAX-обработка через файл ajax.php компонента

Клиентская сторона

Для вызова методов, определенных в ajax.php компонента, используйте параметр mode: 'ajax':

BX.ajax.runComponentAction('my_components:ajax', 'test', {
	mode: 'ajax', // Это означает, что мы хотим вызывать действие из ajax.php, а конкретно метод test. Может принимать class.php - в нем автоСвязывание идет сразу под капотом.
	data: {
		person: 'Hero!' //данные будут автоматически замаплены на параметры метода
	},
	analyticsLabel: {
		viewMode: 'grid',
		filterState: 'closed'
	}
}).then(function (response) {
	console.log(response);
	/**
		 {
			"status": "success",
			"data": "Hi Hero!",
			"errors": []
		}
	 **/
}, function (response) {
	//сюда будут приходить все ответы, у которых status !== 'success'
	console.log(response);
	/**
		{
			"status": "error",
			"errors": [...]
		}
	 **/
});

Особенности:

  • Режим mode: 'ajax':\ Указывает на использование файла ajax.php компонента вместо class.php.
  • Класс контроллера:\ Должен наследоваться от \Bitrix\Main\Engine\Controller (не от CBitrixComponent).

Серверная сторона

Структура компонента:

  • Путь к файлу: /local/components/my_components/ajax/ajax.php
  • Класс контроллера: Наследуется от \Bitrix\Main\Engine\Controller.

Пример класса:

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

class CustomAjaxController extends \Bitrix\Main\Engine\Controller {
  public function configureActions() {
    return [
      'test' => [
        'prefilters' => [], // Фильтры отключены
        'postfilters' => []
      ]
    ];
  }

  public function testAction() {
    return 'Тест пройден';
  }
}
?>  

Обращение к методам модуля

Клиентская сторона

Для вызова методов модуля используйте BX.ajax.runAction():

BX.ajax.runAction('local:lib.api.test.example', {
  data: {
    param1: 'hhh'
  }
}).then(function(response) {
  console.log(response);
});  

Структура действия:

  • Формат действия: <модуль>:<неймспейс>.<контроллер>.<метод>\ Пример: local:lib.api.test.example соответствует:
    • Модуль: local.lib
    • Неймспейс: \Local\Lib\Controller
    • Контроллер: Test
    • Метод: exampleAction

Серверная сторона

1. Регистрация неймспейса:\ В файле .settings.php модуля укажите путь к контроллерам:

<?
// /local/modules/local.lib/.settings.php
return [
  'controllers' => [
    'value' => [
      'namespaces' => [
        '\\Local\\Lib\\Controller' => 'api'
      ]
    ],
    'readonly' => true
  ]
];
?>  

2. Контроллер модуля:

  • Путь к файлу: /local/modules/local.lib/lib/controller/test.php
  • Метод действия: Должен иметь суффикс Action.

Пример класса:

<?
namespace Local\Lib\Controller;
use Bitrix\Main\Engine\Controller;

class Test extends Controller {
  public function configureActions() {
    return [
      'example' => [
        'prefilters' => [] // Фильтры отключены
      ]
    ];
  }

  public static function exampleAction($param2 = 'qwe', $param1 = '') {
    return [
      'asd' => $param1,
      'count' => 300
    ];
  }
}
?>  

Настройка фильтров через configureActions()

Типы фильтров

  1. Prefilters:\ Выполняются до вызова метода действия. Могут отклонить запрос (например, при отсутствии авторизации).
  2. Postfilters:\ Выполняются после вызова метода. Могут модифицировать результат.

Стандартные фильтры

Если configureActions() не переопределен, применяются:

  • Authentication — проверка авторизации.
  • Csrf — проверка CSRF-токена (для POST-запросов).

Примеры настройки:

1. Отключение всех фильтров:

public function configureActions() {
  return [
    'test' => [
      'prefilters' => []
    ]
  ];
}  

2. Кастомизация фильтров:

public function configureActions() {
  return [
    'test' => [
      'prefilters' => [
        new \Bitrix\Main\Engine\ActionFilter\Authentication(),
        new \Bitrix\Main\Engine\ActionFilter\HttpMethod([
          \Bitrix\Main\Web\HttpMethod::PUT
        ])
      ]
    ]
  ];
}  

3. Фильтры по умолчанию:

public function configureActions() {
  return [
    'test' => [] // Применяются стандартные фильтры
  ];
}  

Особенности CSRF-проверки

  • Если в HttpMethod разрешен POST, CSRF-проверка включается автоматически.
  • Для отключения CSRF:
    • Уберите HttpMethod или ограничьте методы (например, только GET).
    • Явно удалите Csrf из prefilters.

Примечания

  • Маппинг параметров:\ Аргументы метода действия связываются с параметрами запроса по имени, независимо от порядка.
  • Типы данных:\ Параметры автоматически приводятся к типам, указанным в объявлении метода.
  • Reflection API:\ Bitrix анализирует аргументы метода через Reflection для корректного присвоения значений.

Стандартные фильтры:\ Располагаются в /bitrix/modules/main/lib/engine/actionfilter/.

 

ТАБЛИЦА

Фильтры
Параметр и описание
Метод
\Bitrix\Main\Engine\ActionFilter\HttpMethod();
Проверяет по какому http методу запускается действие и блокирует выполнение действия, если метод не был перечислен.
$allowedMethods {array}. Список допустимых http методов. По умолчанию GET
				
					__construct(
array $allowedMethods = [self::METHOD_GET]
)
				
			
\Bitrix\Main\Engine\ActionFilter\Authentication();
Проверяет аутентифицирован ли пользователь и блокирует выполнение действия, если проверка не прошла, установив http status 401. Может выполнить редирект на страницу авторизации при необходимости.
$enableRedirect {bool}. Включает или отключает автоматический редирект на страницу авторизации, если проверка не прошла успешно. По умолчанию false.
__construct(
$enableRedirect = false
)
\Bitrix\Main\Engine\ActionFilter\Csrf();
Проверяет наличие и корректность csrf-токена и блокирует выполнение действия, если проверка не прошла.
  • $enabled {bool} Включает или отключает проверку на токен. По умолчанию true.
  • $tokenName {string} Имя, по которому передается значение токена. Используется для поиска в $_GET, $_POST. По умолчанию sessid.
  • $returnNew {bool} Сигнализирует нужно ли возвращать новое значение токена, если проверка прошла неуспешно. Заметим, что возврат осуществляется через \Bitrix\Main\Error::$customData. По умолчанию true.
__construct(
$enabled = true,
$tokenName = 'sessid',
$returnNew = true
)
\Bitrix\Main\Engine\ActionFilter\CloseSession();
Выполнит session_write_close() перед выполнением действия. Будьте внимательны при использовании данного фильтра! Так как после закрытия сессии, все внесенные в неё изменения не будут сохранены. Для понимания работы сессий, стоит ознакомиться с документацией на php.net
$enabled {bool}. Включает или отключает работу фильтра. По умолчанию true
__construct(
$enabled = true
)
\Bitrix\Main\Engine\ActionFilter\Scope();
Позволяет заблокировать определенные действия для указанного scope, например, можно открыть только определенные действия для rest, а все остальные будут доступны только для ajax.
$scopes {int} Перечисление допустимых scopes. Для проверки используются битовые маски. Доступные варианты можно найти в константах класса \Bitrix\Main\Engine\ActionFilter\Scope
__construct(
$scopes
)
\Bitrix\Main\Engine\ActionFilter\Cors();
Устанавливает заголовки ответа для управления CORS.
  • $origin {string} Используется для установки заголовка Access-Control-Allow-Origin. По умолчанию null
  • $credentials {bool} Если true, то устанавливается заголовок Access-Control-Allow-Credentials. По умолчанию false
__construct(
string $origin = null,
bool $credentials = false
)
\Bitrix\Main\Engine\ActionFilter\ContentType();
Фильтр разрешает выполнять действие, только в случае допустимых content-type в запросе. При работе с application/json будет автоматически зарегистрирован объект \Bitrix\Main\Engine\JsonPayload, который можно внедрять в параметры через параметры аякс-действия.
$allowedTypes {array}. Перечисление допустимых content-type. Например, ['application/json']
__construct(
array $allowedTypes
)
\Bitrix\Main\Engine\ActionFilter\PostDecode();
Фильтр перекодирует данные из POST-запроса, если внутренняя кодировка проекта отличается от utf-8

Прямые AJAX-запросы и настройка ЧПУ


Отправка запроса без использования BX.ajax.runComponentAction()

Клиентская реализация

Для выполнения AJAX-запроса напрямую отправляйте данные на эндпоинт /bitrix/services/main/ajax.php, явно указывая параметры:


// Формируем параметры запроса
const url = '/bitrix/services/main/ajax.php?mode=class&c=my_components:ajax&action=test';
const params = new URLSearchParams({
    param1: 'asd',
    sessid: BX.message('bitrix_sessid') // CSRF-токен
});

// Отправка POST-запроса
fetch(url, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: params
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Ошибка:', error));
	

Параметры запроса:

  • mode:
    • class — вызов метода из class.php (наследник CBitrixComponent).
    • ajax — вызов метода из ajax.php (наследник \Bitrix\Main\Engine\Controller).
  • c: Имя компонента в формате <vendor>:<component>.
  • action: Название метода (без суффикса Action).

Особенности:

  1. CSRF-защита:\ Параметр sessid обязателен, если в методе включена проверка CSRF.
  2. Формат ответа:\ Ответ возвращается в виде JSON-объекта с полями status, data и errors.

Настройка ЧПУ для AJAX-запросов

Серверная реализация

Добавьте правило в urlrewrite.php, чтобы преобразовывать «человекопонятные» URL в параметры для ajax.php:

// /bitrix/urlrewrite.php
$arUrlRewrite = [
  [
    "CONDITION" => "#^/api/rest-component/([a-zA-Z0-9]+)/([a-zA-Z0-9\.]+)/([a-zA-Z0-9]+)/?.*#",
    "RULE" => "mode=class&c=$1:$2&action=$3",
    "PATH" => "/bitrix/services/main/ajax.php",
  ],
];  

Расшифровка правила:

  • CONDITION: Регулярное выражение для匹配 URL:
    • ([a-zA-Z0-9]+) — vendor компонента.
    • ([a-zA-Z0-9\.]+) — название компонента.
    • ([a-zA-Z0-9]+) — метод (action).
  • RULE: Подстановка параметров:
    • mode=class — режим работы с class.php.
    • c=$1:$2 — имя компонента в формате <vendor>:<component>.
    • action=$3 — вызываемый метод.

Пример использования ЧПУ

function sendFeedback(form) {
  const route = "/api/rest-component/machaon/feedback/send/";
  const data = $(form).serialize();
  $.post(route, data, function(response) {
    console.log(response);
  });
}  

Результат:

  • Запрос к /api/rest-component/machaon/feedback/send/ преобразуется в:

    /bitrix/services/main/ajax.php?mode=class&c=machaon:feedback&action=send  

Примечания

  1. Безопасность:
    • Не отключайте CSRF-проверку для методов, изменяющих данные.
    • Для GET-запросов CSRF-токен не требуется.
  2. Типы запросов:
    • Используйте POST для методов, изменяющих состояние системы.
  3. Обработка ошибок:
    • Проверяйте статус ответа (response.status === 'success').
  4. Стандартные фильтры:
    • При mode=class применяются фильтры из configureActions() компонента.

Пример ответа при ошибке:

{
  "status": "error",
  "errors": ["Недостаточно прав"],
  "data": null
}  

Пример ответа при успехе:

{
  "status": "success",
  "data": {
    "result": "Данные сохранены"
  }
}