Польза
Приём аякса на бэке

Шаблон оболочки обработчиков аякс-запросов

29 апреля 2020 года
Битрикс, аякс

Ниже размещён шаблон, который поможет тем, кто заморочился сборкой страницы для приёма и обработки аякс-запроса в Битриксе. Представлена оболочка, состоящая из пре-шапки и тела обработчика. Предполагается, что пре-шапка общая для всех подобных обработчиков, её подключаем в начале каждого из них.

Пре-шапка

Файл: /ajax/common_header.php

use Bitrix\Main\Context;

set_time_limit(0);
error_reporting(E_ERROR);

// Не собирать статистику
@define('STOP_STATISTICS', true);
@define('NO_KEEP_STATISTIC', true);
@define('NO_AGENT_STATISTIC', 'Y');

// Погасить монитор производительности
@define('PERFMON_STOP', true);

// Пропустить проверку на доступ к файлу
// (на этапе подключения главного модуля)
@define('NOT_CHECK_PERMISSIONS', true);

// Чтобы если мы в режиме отладки, не сыпались ошибки
@define('PUBLIC_AJAX_MODE', true);

// Пропустить шаг проверки,
// нужно ли на хите выполнять агентов
@define('NO_AGENT_CHECK', true);

require(
    $_SERVER['DOCUMENT_ROOT']
    . '/bitrix/modules/main/include/prolog_before.php'
);

// ...например, чтобы отключить действия типа
// "объединять css-, js-файлы"
@define('ADMIN_SECTION', true);

// Отключаем режим правки (путает нам json), статистику
$GLOBALS['APPLICATION']->SetShowIncludeAreas(false);

// Не показывать статистику страницы
$_SESSION['SESS_SHOW_TIME_EXEC'] = null;
$_SESSION['SESS_SHOW_INCLUDE_TIME_EXEC'] = null;
$GLOBALS['DB']->ShowSqlStat = false;


$context = Context::getCurrent();
$posts = $context->getRequest()->getPostList()->toArray();

// Если нам передан идентификатор сессии для проверки
// Можно доработать на то, что идентификатор ДОЛЖЕН быть передан
$bxsessid = $posts['bxsessid'] ?? null;
if ($bxsessid && bitrix_sessid() !== $bxsessid) {
    die('Access denied');
}

// При вызове через аякс обязательно ожидается реферер
$referer = $context->getServer()->get('HTTP_REFERER');

// ...и сигнал мы разрешаем только с трастовых доменов
$trustedDomains = [
    'burlaka.studio',
    'example.burlaka.studio',
    'realcommenter.com',
];

$allowedRegExp = sprintf(
    '~https?://(%s)/~is' . BX_UTF_PCRE_MODIFIER,
    str_replace(
        '.', '\.',
        implode('|', $trustedDomains)
    )
);

$trusted = ($referer && preg_match($allowedRegExp, $referer));

if (
    !defined('B_PROLOG_INCLUDED')
    || B_PROLOG_INCLUDED !== true
    || !$trusted
) {
    die('Access Denied');
}

// Уважительно относимся к clear_cache=Y в урле реферера
// Обязательно нужно вернуть N, если не Y
$sessClearFlag = 'N';

if (strpos($referer, 'clear_cache=Y') !== false) {
    global $USER;

    // Авторизован юзер и у него есть доступ
    // к управлению кешем на хите
    if (
        is_object($USER)
        && $USER->CanDoOperation('cache_control')
    ) {
        $sessClearFlag = 'Y';
    }
}

$_SESSION['SESS_CLEAR_CACHE'] = $sessClearFlag;

Файл-обработчик

Файл в папке /ajax/ (рядом с common_header.php)

// Подключаем пре-шапку
include_once __DIR__ . '/common_header.php';

// !!!!!
// html-mode
// (если мы возвращаем в ответе html)

// ... и хотим чтобы js, css были корректно
// обработаны на фронте
$APPLICATION->ShowAjaxHead(false, true, false, true);

// ... если мы писали что-то в управляемый кеш
// или устанавливали куки
// или должны отработать обработчики на эпилоге
require_once(
    $_SERVER['DOCUMENT_ROOT'].
    '/bitrix/modules/main/include/epilog_after.php'
);

// !!!!!
// json-mode

// Пример упаковки собранного массива в json
// ... метод внутри учитывает кодировку проекта
echo \Bitrix\Main\Web\Json::encode($json);

Обсуждение статьи 1

Написать
Alexey
Супер. От себя добавлю что если нет записи в сессию, то до подключения пролога можно добавить define('BX_SECURITY_SESSION_READONLY', true); для того что бы не блокировать сессию. А когда сессия вообще не нужна — define('BX_SECURITY_SESSION_VIRTUAL', true);
Ответить
Написать