@ -76,8 +76,8 @@ RL_INDEX_BLOCKED_IPS = 'rl:index:blocked_ips'
RL_INDEX_BLOCKED_USERS = ' rl:index:blocked_users '
RL_INDEX_BLOCKED_USERS = ' rl:index:blocked_users '
# API-specific rate limit keys — scope limited to /api/, never written by non-/api/ paths.
# API-specific rate limit keys — scope limited to /api/, never written by non-/api/ paths.
RL_API_IP_REQUESTS = ' rl:api:ip: {ip} :reqs '
RL_API_IP_REQUESTS = ' rl:api:ns: {ns} : ip: {ip} :reqs '
RL_API_IP_BLOCKED = ' rl:api:ip: {ip} :blocked '
RL_API_IP_BLOCKED = ' rl:api:ns: {ns} : ip: {ip} :blocked '
RL_INDEX_API_BLOCKED_IPS = ' rl:index:api_blocked_ips '
RL_INDEX_API_BLOCKED_IPS = ' rl:index:api_blocked_ips '
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
@ -404,7 +404,7 @@ class RateLimitMiddleware:
return self . _api_block_response ( ' global_ip_blocked ' )
return self . _api_block_response ( ' global_ip_blocked ' )
# 4. API-specific block (blocks /api/ only, never set by non-/api/ paths)
# 4. API-specific block (blocks /api/ only, never set by non-/api/ paths)
if self . _rl_cache . get ( RL_API_IP_BLOCKED . format ( ip = ip ) ) :
if self . _rl_cache . get ( RL_API_IP_BLOCKED . format ( ns = _NAMESPACE , ip = ip ) ) :
logger . warning (
logger . warning (
' api_rate_limit_block reason=api_ip_blocked ip= %s path= %s user_agent= %s ' ,
' api_rate_limit_block reason=api_ip_blocked ip= %s path= %s user_agent= %s ' ,
ip , request . path , request . META . get ( ' HTTP_USER_AGENT ' , ' ' ) ,
ip , request . path , request . META . get ( ' HTTP_USER_AGENT ' , ' ' ) ,
@ -430,9 +430,9 @@ class RateLimitMiddleware:
# Auth is not exempt: authenticating must not bypass this cap.
# Auth is not exempt: authenticating must not bypass this cap.
# Writes rl:api:ip:<ip>:blocked only — never rl:ip:<ip>:blocked.
# Writes rl:api:ip:<ip>:blocked only — never rl:ip:<ip>:blocked.
if self . api_rate_limit_enabled :
if self . api_rate_limit_enabled :
count = self . _incr_with_ttl ( RL_API_IP_REQUESTS . format ( ip = ip ) , self . api_window )
count = self . _incr_with_ttl ( RL_API_IP_REQUESTS . format ( ns = _NAMESPACE , ip = ip ) , self . api_window )
if count > = self . api_threshold :
if count > = self . api_threshold :
_set_block ( RL_API_IP_BLOCKED . format ( ip = ip ) , RL_INDEX_API_BLOCKED_IPS , self . api_block_seconds )
_set_block ( RL_API_IP_BLOCKED . format ( ns = _NAMESPACE , ip = ip ) , RL_INDEX_API_BLOCKED_IPS , self . api_block_seconds )
logger . warning (
logger . warning (
' api_rate_limit_block reason=api_threshold_exceeded '
' api_rate_limit_block reason=api_threshold_exceeded '
' ip= %s path= %s user_agent= %s count= %s threshold= %s ' ,
' ip= %s path= %s user_agent= %s count= %s threshold= %s ' ,