Почему стандартное кэширование REST API не работает с авторизацией и куками
WP REST API часто используется для динамического взаимодействия с сайтом, включая отправку и получение данных, требующих авторизации. Стандартные методы кэширования (например, WP Super Cache, W3 Total Cache) не учитывают авторизационные куки и заголовки, что приводит к выдаче одинакового кешированного контента разным пользователям или к выдаче неавторизованного контента.
Основная причина — REST API ответы зависят от Authorization заголовков и cookie пользователя, а кеш не различает эти параметры по умолчанию.
Диагностика проблемы: как проверить, что кэш не учитывает авторизацию
- Отправьте REST API запрос с авторизационным токеном или куками и запомните ответ.
- Очистите кеш и отправьте запрос от другого пользователя (или без авторизации).
- Если ответы совпадают — кэш не учитывает авторизацию.
- Проверьте заголовки HTTP ответа: при кэшировании могут отсутствовать заголовки, указывающие на различия в сессиях.
Пример CURL запроса для теста авторизации:
curl -X GET https://example.com/wp-json/wp/v2/posts -H "Authorization: Bearer YOUR_TOKEN"Повторите запрос без заголовка Authorization и сравните ответы.
Пошаговое решение: кэширование WP REST API с поддержкой авторизации и куков
1. Создание уникального ключа кеша с учетом куков и заголовков
Для корректного кеширования нужно формировать ключ кеша, включающий:
- JWT или Bearer токен из заголовков
- пользовательские cookie, влияющие на вывод
- параметры URL запроса
Пример кода для генерации ключа кеша в функции-обработчике:
function generate_cache_key(\WP_REST_Request $request) {
$url = $request->get_route() . '?' . http_build_query($request->get_query_params());
$auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
$cookies = $_COOKIE;
// Выбираем только релевантные куки, например, для авторизации
$relevant_cookies = [];
foreach ($cookies as $name => $value) {
if (strpos($name, 'wordpress_logged_in_') === 0) {
$relevant_cookies[$name] = $value;
}
}
$key_string = $url . '|' . $auth_header . '|' . json_encode($relevant_cookies);
return 'rest_cache_' . md5($key_string);
}2. Использование фильтра для реализации кэширования REST API
Хук rest_pre_echo_response позволяет перехватить ответ и сохранить его в кеш, а rest_pre_dispatch — вернуть кеш, если есть. Пример реализации:
add_filter('rest_pre_dispatch', function($response, $server, $request) {
$cache_key = generate_cache_key($request);
$cached = get_transient($cache_key);
if ($cached !== false) {
return rest_ensure_response(json_decode($cached, true));
}
return $response;
}, 10, 3);
add_filter('rest_pre_echo_response', function($response, $server, $request) {
$cache_key = generate_cache_key($request);
$data = rest_get_server()->response_to_data($response, true);
set_transient($cache_key, json_encode($data), HOUR_IN_SECONDS);
return $response;
}, 10, 3);3. Ограничение кэширования только для GET-запросов и публичных эндпоинтов
Лучше не кешировать POST, PUT, DELETE запросы и приватные эндпоинты. Добавим проверку:
function should_cache_request(\WP_REST_Request $request) {
if ($request->get_method() !== 'GET') {
return false;
}
$route = $request->get_route();
// Пример: кешируем только публичные эндпоинты
if (strpos($route, '/wp/v2/posts') === 0) {
return true;
}
return false;
}И применяем в фильтрах:
add_filter('rest_pre_dispatch', function($response, $server, $request) {
if (!should_cache_request($request)) {
return $response;
}
// далее код кеширования
}, 10, 3);Проверка результата после внедрения
- Повторите тесты CURL с авторизацией и без.
- Убедитесь, что разные пользователи получают корректный, персонализированный ответ.
- Проверьте время отклика: при повторных запросах должен использоваться кеш.
- Включите логирование вызовов
set_transientиget_transientили используйте дебаг-плагины для проверки кеша.
Частые ошибки и как исправить
- Кеширование POST-запросов: приводит к ошибкам, т.к. POST не должен кешироваться. Решение — фильтровать по методу запроса.
- Игнорирование авторизационных куков и заголовков: выдача одинакового контента всем пользователям. Решение — включить их в ключ кеша.
- Слишком длинные ключи кеша: могут вызвать проблемы с базой данных или файловой системой. Решение — использовать хеширование (md5).
- Отсутствие очистки кеша при изменении данных: пользователи видят устаревшую информацию. Решение — добавлять хуки очистки кеша при обновлении постов, пользователей и т.п.
Практические советы по безопасности и производительности
- Не храните в кеше чувствительные данные без шифрования.
- Используйте
set_transientс ограниченным временем жизни (например, 1 час). - Для масштабных проектов рассмотрите внедрение кеша в Redis или Memcached с аналогичной логикой ключей.
- При использовании авторизационных заголовков убедитесь, что они не попадут в сторонние логи.
- Тестируйте на staging-средах перед внедрением в продакшн.
Сравнительная таблица методов кэширования REST API с авторизацией
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
| Файловый кеш с WP Super Cache | Простота, интеграция с сайтом | Нет поддержки авторизации, сложность кастомизации | Используется для статических страниц |
| Transient API с учетом куков и заголовков | Гибкость, поддержка авторизации | Ограничен по размеру, подходит для средних нагрузок | Код из статьи |
| Redis/Memcached с кастомной логикой | Высокая производительность, масштабируемость | Требует настройки сервера и дополнительного кода | В продакшн для больших сайтов |