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