SessionProxy: лимиты в Redis и blacklist
Архитектурная схема (archify) →
Почему Redis, а не только Postgres
Лимиты (usage_counters: число запросов, объём трафика, число нарушений) проверяются в Redis на КАЖДЫЙ запрос гостя — это быстрый путь принятия решения «пускать или нет» без похода в реляционную БД на каждый чих. При активной ссылке это могут быть десятки проверок в секунду.
Postgres при этом не выброшен из схемы — он остаётся источником истины для отчётности (реальные агрегаты за всё время) и для восстановления счётчиков, если Redis перезапустили и потерял состояние: при первом обращении к ссылке после рестарта Redis происходит warm load — счётчик подтягивается обратно из Postgres, а не стартует с нуля молча.
Такое разделение — стандартный паттерн «Redis для горячего пути принятия решений, Postgres для истины и восстановления» — работает здесь именно потому, что потеря нескольких секунд точности счётчика (между рестартом Redis и следующим обращением) не критична для бизнес-логики лимитов, в отличие, например, от списания денег.
Правило «самый строгий лимит выигрывает»
Одна shared_link может быть привязана сразу к нескольким access_policies через таблицу-связку link_policies — например, общая политика организации (макс. 1000 запросов) и персональная политика владельца ссылки (макс. 100 запросов).
Эти политики схлопываются в ОДИН эффективный лимит по правилу: берётся минимум по каждому полю (max_requests, max_bytes_transferred, max_ttl_seconds, max_violation_count) среди всех привязанных политик, а NULL в это сравнение не участвует (трактуется как «эта политика не ограничивает данное поле», а не как «ноль»).
Практический пример: если политика A разрешает 1000 запросов без ограничения по трафику (max_bytes_transferred = NULL), а политика B разрешает 100 запросов и 50 МБ трафика — эффективный лимит будет 100 запросов (минимум из 1000 и 100) и 50 МБ трафика (единственное заданное значение, раз у A оно NULL).
Blacklist проверяется по правильному пути
Пути в blacklisted_endpoints записаны и проверяются в терминах реального пути НА ЦЕЛЕВОМ сайте (например, /settings), а не по обёрнутому гостевому URL прокси (/r/{token}/settings).
Если бы проверка шла по гостевому URL, было бы достаточно любой обфускации на стороне клиента прокси (лишний параметр запроса, изменённый регистр, кодирование части пути), чтобы обойти правило — сама структура /r/{token}/... не гарантирует однозначного соответствия одному и тому же реальному пути. Проверка по факту резолвленного целевого пути устраняет этот класс обходов целиком, а не патчит его точечно под конкретный обнаруженный трюк.
Пустой список заблокированных методов у правила в endpoint_blocked_methods трактуется как «блокировать ВСЕ методы для этого пути», непустой список — как «блокировать только перечисленные» (например, разрешить GET /export, но заблокировать POST /export, если экспорт можно смотреть, но не инициировать через прокси).