from django.core.handlers.wsgi import WSGIRequest


def get_client_ip(request: WSGIRequest) -> str | None:
    """
    Attempt to obtain the client's connecting IP from given request.

    This will try to follow various commonly used proxy forward headers, or if none
    of those are set, eventually falling back to TCP/IP request's REMOTE_ADDR.

    NOTE: In some cases, these headers might contain more than a single IP address,
    instead being a chain of IPs as the request got forwarded through various reverse
    proxy servers or load balancers. Meaning this function isn't guaranteed to return
    a well-formed IP address.

    WARNING: The IP headers used to obtain the final IP address are blindly trusted.
    If the user sets these headers manually while sending the request and their chosen
    header is higher in the list of headers we're trying, they will override any proxy,
    and could insert a fake IP.

    After consultation, this potential security issue and format inconsistency was deemed
    acceptable.
    """
    ip_headers = [
        "HTTP_CLIENT_IP",
        "HTTP_X_FORWARDED_FOR",
        "HTTP_X_FORWARDED",
        "HTTP_FORWARDED_FOR",
        "HTTP_FORWARDED",
        "REMOTE_ADDR",
    ]

    for ip_header in ip_headers:
        client_ip = request.META.get(ip_header)
        if client_ip:
            return client_ip
    return None
