From 504e1a563915dca832cb99c6581885395a7c67b1 Mon Sep 17 00:00:00 2001 From: Edward Oliveira Date: Tue, 26 May 2026 20:39:34 -0300 Subject: [PATCH] Rename quota key constants and Redis keys with api_ prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - QUOTA_DAILY_HASH → API_QUOTA_DAILY_HASH - QUOTA_WEEKLY_HASH → API_QUOTA_WEEKLY_HASH - Redis key templates: quota:{ns}:... → api_quota:{ns}:... - Local variables d_hash/w_hash → api_d_hash/api_w_hash in _check_api_quota - Update test imports and assertions accordingly Migration: flush old keys with redis-cli -n 1 --scan --pattern 'quota:*' | xargs -L 100 redis-cli -n 1 DEL Co-Authored-By: Claude Sonnet 4.6 --- sapl/middleware/ratelimit.py | 16 ++++++++-------- sapl/middleware/test_ratelimiter.py | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sapl/middleware/ratelimit.py b/sapl/middleware/ratelimit.py index ee8abc5a4..146de9474 100644 --- a/sapl/middleware/ratelimit.py +++ b/sapl/middleware/ratelimit.py @@ -82,15 +82,15 @@ RL_INDEX_API_BLOCKED_IPS = 'rl:index:api_blocked_ips' # --------------------------------------------------------------------------- # API quota keys — per-tenant HASH, one key per period. -# Structure: HASH key = quota:{ns}:daily:{date} field = {ip} value = counter -# HASH key = quota:{ns}:weekly:{week} field = {ip} value = counter +# Structure: HASH key = api_quota:{ns}:daily:{date} field = {ip} value = counter +# HASH key = api_quota:{ns}:weekly:{week} field = {ip} value = counter # Weekly key uses ISO week notation (yyyy-Www) — unambiguous, Monday-anchored. # TTL set once on hash creation (Lua TTL guard); resets are implicit in the # date/week embedded in the key name. Fields are IPs; no per-field TTL. # Memory: ~63 bytes/field vs ~148 bytes for per-IP STRING keys (~57% saving). # --------------------------------------------------------------------------- -QUOTA_DAILY_HASH = 'quota:{ns}:daily:{date}' -QUOTA_WEEKLY_HASH = 'quota:{ns}:weekly:{week}' +API_QUOTA_DAILY_HASH = 'api_quota:{ns}:daily:{date}' +API_QUOTA_WEEKLY_HASH = 'api_quota:{ns}:weekly:{week}' # --------------------------------------------------------------------------- # Bot UA fragments @@ -607,13 +607,13 @@ class RateLimitMiddleware: week_str = f'{iso[0]}-W{iso[1]:02d}' ip = get_client_ip(request) - d_hash = QUOTA_DAILY_HASH.format(ns=_NAMESPACE, date=date_str) - w_hash = QUOTA_WEEKLY_HASH.format(ns=_NAMESPACE, week=week_str) + api_d_hash = API_QUOTA_DAILY_HASH.format(ns=_NAMESPACE, date=date_str) + api_w_hash = API_QUOTA_WEEKLY_HASH.format(ns=_NAMESPACE, week=week_str) try: - if _hincrby_with_ttl(d_hash, ip, 86400) > self.api_quota_daily: + if _hincrby_with_ttl(api_d_hash, ip, 86400) > self.api_quota_daily: return 'daily' - if _hincrby_with_ttl(w_hash, ip, 7 * 86400) > self.api_quota_weekly: + if _hincrby_with_ttl(api_w_hash, ip, 7 * 86400) > self.api_quota_weekly: return 'weekly' except Exception: pass # fail open — quota not enforced when Redis unavailable diff --git a/sapl/middleware/test_ratelimiter.py b/sapl/middleware/test_ratelimiter.py index 3dd359c43..8eaf73841 100644 --- a/sapl/middleware/test_ratelimiter.py +++ b/sapl/middleware/test_ratelimiter.py @@ -20,8 +20,8 @@ from sapl.middleware.ratelimit import ( _parse_rate, get_client_ip, make_ratelimit_cache_key, - QUOTA_DAILY_HASH, - QUOTA_WEEKLY_HASH, + API_QUOTA_DAILY_HASH, + API_QUOTA_WEEKLY_HASH, RateLimitMiddleware, RL_API_IP_BLOCKED, RL_API_IP_REQUESTS, @@ -652,8 +652,8 @@ def test_api_quota_uses_hash_keys(): today = date.today() iso = today.isocalendar() - expected_daily_hash = QUOTA_DAILY_HASH.format(ns=_NAMESPACE, date=today.isoformat()) - expected_weekly_hash = QUOTA_WEEKLY_HASH.format( + expected_daily_hash = API_QUOTA_DAILY_HASH.format(ns=_NAMESPACE, date=today.isoformat()) + expected_weekly_hash = API_QUOTA_WEEKLY_HASH.format( ns=_NAMESPACE, week=f'{iso[0]}-W{iso[1]:02d}' ) calls = mock_h.call_args_list