Help for web.server.is_local

Sample CLI

gway web.server is-local

References

Full Code

def is_local(request=None, host=None):
    """
    Returns True if the active HTTP request originates from the same machine
    that the server is running on (i.e., local request). Supports both
    Bottle and FastAPI (ASGI/WSGI).
    
    Args:
        request: Optionally, the request object (Bottle, Starlette, or FastAPI Request).
        host: Optionally, the bound host (for override or testing).
        
    Returns:
        bool: True if request is from localhost, else False.
    """
    try:
        # --- Try to infer the active request if not given ---
        if request is None:
            # Try FastAPI/Starlette
            try:
                from starlette.requests import Request as StarletteRequest
                import contextvars
                req_var = contextvars.ContextVar("request")
                request = req_var.get()
            except Exception:
                pass
            # Try Bottle global
            if request is None:
                try:
                    from bottle import request as bottle_request
                    request = bottle_request
                except ImportError:
                    request = None

        # --- Get remote address from request ---
        remote_addr = None
        if request is not None:
            # FastAPI/Starlette: request.client.host
            remote_addr = getattr(getattr(request, "client", None), "host", None)
            # Bottle: request.remote_addr
            if not remote_addr:
                remote_addr = getattr(request, "remote_addr", None)
            # Try request.environ['REMOTE_ADDR']
            if not remote_addr and hasattr(request, "environ"):
                remote_addr = request.environ.get("REMOTE_ADDR")
        else:
            # No request in context
            return False

        # --- Get server bound address ---
        if host is None:
            from gway import gw
            host = gw.resolve("[WEBSITE_HOST|127.0.0.1]")
        # If host is empty or all-interfaces, assume not local
        if not host or host in ("0.0.0.0", "::", ""):
            return False

        # --- Normalize addresses for comparison ---
        def _norm(addr):
            if addr in ("localhost",):
                return "127.0.0.1"
            if addr in ("::1",):
                return "127.0.0.1"
            try:
                # Try resolving hostname
                return socket.gethostbyname(addr)
            except Exception:
                return addr

        remote_ip = _norm(remote_addr)
        host_ip = _norm(host)
        # Accept both IPv4 and IPv6 loopback equivalence
        return remote_ip.startswith("127.") or remote_ip == host_ip
    except Exception as ex:
        import traceback
        print(f"[is_local] error: {ex}\n{traceback.format_exc()}")
        return False