45 lines
1.2 KiB
Python
45 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
import ipaddress
|
|
|
|
|
|
def _normalize_ip(value: str | None) -> str | None:
|
|
if not value:
|
|
return None
|
|
candidate = value.strip()
|
|
if not candidate:
|
|
return None
|
|
if candidate.startswith("[") and "]" in candidate:
|
|
candidate = candidate[1 : candidate.index("]")]
|
|
elif candidate.count(":") == 1 and candidate.rsplit(":", 1)[1].isdigit():
|
|
candidate = candidate.rsplit(":", 1)[0]
|
|
try:
|
|
return str(ipaddress.ip_address(candidate))
|
|
except ValueError:
|
|
return None
|
|
|
|
|
|
def get_client_ip(request) -> str | None:
|
|
if not request:
|
|
return None
|
|
x_real_ip = _normalize_ip(request.META.get("HTTP_X_REAL_IP"))
|
|
if x_real_ip:
|
|
return x_real_ip
|
|
forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR", "")
|
|
if forwarded_for:
|
|
for part in forwarded_for.split(","):
|
|
ip = _normalize_ip(part)
|
|
if ip:
|
|
return ip
|
|
return _normalize_ip(request.META.get("REMOTE_ADDR"))
|
|
|
|
|
|
def get_request_id(request) -> str:
|
|
if not request:
|
|
return ""
|
|
return (
|
|
request.META.get("HTTP_X_REQUEST_ID")
|
|
or request.META.get("HTTP_X_CORRELATION_ID")
|
|
or ""
|
|
)
|