AnswerDotAI / AnswerDotAI/fasthtml
[FEATURE] Support Base URL / Starlette Prefix
- Dominant language
- Jupyter Notebook
- Stars
- 7k
- Forks
- 319
- Avg merge
- 28m
- Merged PRs (30d)
- 3
Description
**Is your feature request related to a problem? Please describe.**
I want to run FastHTML application's within my existing web app under a dynamic url prefix. For example: https://apps.aihype.com/username/appname.
**Describe the solution you'd like**
Streamlit let's you configure `--server.baseUrlPath=/username/appname` when starting an app. It will be trickier with FastHTML as both the backend and the frontend need to know about this, but I think it can be done with a settings / environment variable.
**Example code**
I was able to get this mostly working by manually wrapping the app in a custom entrypoint and adding some headers to the generated HTML:
**Wrapper**
```python
os.environ["BASE_PREFIX"] = prefix
if prefix:
print("Prefix detected, wrapping app...")
orig_entrypoint = os.path.basename(entrypoint)
with open("prefixed_app.py", "w") as f:
f.write(f"""from starlette.applications import Starlette
from starlette.routing import Mount
from {orig_entrypoint.replace('.py', '')} import app as orig_app, serve
routes = [Mount("{prefix}", orig_app)]
app = Starlette(routes=routes)
serve(reload=False)""")
```
**App**
```python
headers = (...)
if os.getenv("BASE_PREFIX"):
prefix = os.getenv("BASE_PREFIX")
headers = (
Base(
href=prefix
),
Script(
f"""document.addEventListener('DOMContentLoaded', () => {{
document.body.addEventListener('htmx:configRequest', (event) => {{
event.detail.path = `{prefix}${{event.detail.path}}`
}})
}});
""")
) + headers
... = fast_app("rad.db", hdrs=headers, ...)
```
**Similar implementations**
1. [Streamlit](https://docs.streamlit.io/develop/api-reference/configuration/config.toml) - See `baseUrlPath` in the Server section
**Problem solved**
This would allow users to host multiple apps on a single domain behind an authenticated proxy. It also enables 3rd parties to support hosting fasthtml apps within their existing platforms.
**Additional context**
I imagine my initial approach doesn't catch all cases. For instance I noticed when `live=True` the websocket is not getting re-routed when I mounted the existing Starlette app. The `
Contributor guide
Assessment
This issue has not been assessed yet.