Skip to content

woodglue.ui_support

Helpers for code running inside a Process-backed UI.

Helpers for code running inside a Process-backed UI, such as a Streamlit app.

woodglue's proxy adds two headers to every request it forwards (see woodglue.apps.ui_proxy):

  • X-Woodglue-User: JSON describing the viewing User.
  • X-Woodglue-Token: a Delegated Token for that User's Session, present when they signed in through the browser.

and starts the process with WOODGLUE_URL, the API's loopback address. current_client combines them into a woodglue.client.WoodglueClient that calls the API as the viewer, with exactly their Grants:

import asyncio

import streamlit as st
from woodglue.ui_support import current_client, current_user

me = current_user()
st.write(f"Hello, {me.name if me else 'stranger'}")


async def load_totals():
    return await current_client().call("reports.daily_totals", day="2026-10-01")


st.write(asyncio.run(load_totals()))

Streamlit runs the script without an event loop, so make the client inside the coroutine that asyncio.run drives, as above.

Without headers, both read Streamlit's st.context.headers; other frameworks pass their request headers. The headers are only trustworthy behind woodglue, which strips client-sent copies, so the UI process must listen on loopback only, as it does when woodglue runs it.

current_user(headers=None)

The User viewing the UI, or None if the request did not come through woodglue.

>>> current_user({"x-woodglue-user": '{"id": "u1", "name": "Ann", "roles": ["viewer"]}'})
ViewingUser(id='u1', name='Ann', email=None, roles=('viewer',))
>>> current_user({}) is None
True
Source code in src/woodglue/ui_support.py
def current_user(headers: Mapping[str, str] | None = None) -> ViewingUser | None:
    """
    The User viewing the UI, or `None` if the request did not come through
    woodglue.

    >>> current_user({"x-woodglue-user": '{"id": "u1", "name": "Ann", "roles": ["viewer"]}'})
    ViewingUser(id='u1', name='Ann', email=None, roles=('viewer',))
    >>> current_user({}) is None
    True
    """
    raw = _header(headers if headers is not None else _streamlit_headers(), USER_HEADER)
    if raw is None:
        return None
    data = json.loads(raw)
    return ViewingUser(
        id=data.get("id"),
        name=data.get("name", ""),
        email=data.get("email"),
        roles=tuple(data.get("roles", ())),
    )

current_client(headers=None, base_url=None)

A client calling the woodglue API as the viewing User. base_url defaults to WOODGLUE_URL. Without a Delegated Token (e.g. auth is disabled), the client sends no credential.

Source code in src/woodglue/ui_support.py
def current_client(
    headers: Mapping[str, str] | None = None, base_url: str | None = None
) -> WoodglueClient:
    """
    A client calling the woodglue API as the viewing User. `base_url` defaults
    to `WOODGLUE_URL`. Without a Delegated Token (e.g. auth is disabled), the
    client sends no credential.
    """
    url = base_url or os.environ.get("WOODGLUE_URL")
    if not url:
        raise RuntimeError("WOODGLUE_URL is not set; is this process running under woodglue?")
    token = _header(headers if headers is not None else _streamlit_headers(), TOKEN_HEADER)
    return WoodglueClient(url, token=token)