| 173 | |
| 174 | |
| 175 | def _extract_client_ip(request: Request) -> str: |
| 176 | if settings.SECURITY_TRUST_PROXY_HEADERS: |
| 177 | for header_name in ("CF-Connecting-IP", "X-Forwarded-For", "X-Real-IP"): |
| 178 | value = (request.headers.get(header_name) or "").strip() |
| 179 | if not value: |
| 180 | continue |
| 181 | if header_name == "X-Forwarded-For": |
| 182 | first_hop = value.split(",", 1)[0].strip() |
| 183 | if first_hop: |
| 184 | return first_hop |
| 185 | continue |
| 186 | return value |
| 187 | if request.client and request.client.host: |
| 188 | return str(request.client.host) |
| 189 | return "unknown" |
| 190 | |
| 191 | |
| 192 | def _build_rate_limit_key(ip: str, bucket: str) -> str: |