datasette-auth-existing-cookies/datasette_auth_existing_cookies/__init__.py
from datasette import hookimplfrom cachetools import TTLCacheimport httpx@hookimpldef actor_from_request(datasette, request):config = datasette.plugin_config("datasette-auth-existing-cookies") or {}api_url = config.get("api_url")if api_url is None:return Nonecookies_to_pass = config.get("cookies")headers_to_pass = config.get("headers")ttl = config.get("ttl")if ttl is not None:if getattr(datasette, "_auth_existing_cookies_cache", None) is None:datasette._auth_existing_cookies_cache = TTLCache(1000, ttl=ttl)else:datasette._auth_existing_cookies_cache = Noneasync def inner():if cookies_to_pass:cookies = {key: request.cookies.get(key)for key in cookies_to_passif request.cookies.get(key)}else:# Send them allcookies = request.cookiesheader_params = {}if headers_to_pass:for header in headers_to_pass:value = request.headers.get(header.lower())if value is not None:header_params[header.lower()] = valuecache_key = Noneif datasette._auth_existing_cookies_cache is not None:# Maybe there's a cached version of this?# Cache key is a tuple-of-tuples-of-tuples, (cookies, headers)# where cookies and headers are sorted tuples of (key, value) pairscookies_for_key = tuple(sorted(cookies.items()))headers_for_key = tuple(sorted(header_params.items()))cache_key = (cookies_for_key, headers_for_key)if cache_key in datasette._auth_existing_cookies_cache:return datasette._auth_existing_cookies_cache[cache_key]async with httpx.AsyncClient() as client:response = await client.get(api_url, params=header_params, cookies=cookies)if response.status_code != 200:actor = Noneelse:actor = response.json()if datasette._auth_existing_cookies_cache is not None:datasette._auth_existing_cookies_cache[cache_key] = actorreturn actorreturn inner