From 5bc8ef2566917e5c3a1710dcffd6b7dc46180f50 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 15 Apr 2026 20:29:49 -0400 Subject: [PATCH] feat(settings): add public_base_url helper with request.host_url fallback --- roundtable/core/settings.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/roundtable/core/settings.py b/roundtable/core/settings.py index e924565..c6ae158 100644 --- a/roundtable/core/settings.py +++ b/roundtable/core/settings.py @@ -202,3 +202,27 @@ def load_settings_sync(db_url: str) -> dict[str, Any]: if key.startswith("plugin.") and key not in out: out[key] = value return out + + +# ───────────────────────────────────────────────────────────────────────────── +# External URL helper +# ───────────────────────────────────────────────────────────────────────────── + +def public_base_url(request) -> str: + """Return the externally-reachable base URL for this Roundtable instance. + + Prefers the admin-configured 'general.public_base_url' setting (cached in + current_app.config['PUBLIC_BASE_URL']) when set. Falls back to + request.host_url stripped of its trailing slash, so unconfigured + single-hostname installs keep working with zero config. + + Use this — NOT request.host_url — anywhere you build a URL that will be + consumed by something outside this Quart request: install scripts, share + links, alert notifications, webhook callbacks. The Host header is not + reliable behind proxies or on multi-hostname deployments. + """ + from quart import current_app + configured = (current_app.config.get("PUBLIC_BASE_URL") or "").strip() + if configured: + return configured.rstrip("/") + return request.host_url.rstrip("/")