Skip to content

App.run() does not serve a mounted ASGI app (routes=[Mount(...)]) that works with uvicorn.run(app) #1568

Open

Description

@Vital-Fernandez

Summary

Hi, I want to update my virtual observatory app (https://specsy.streamlit.app/) so that the user can download data selections from a Bokeh figure.

I have managed to get a working version by embedding a Bokeh server app (Bokeh 3.10 BokehASGI) in the Streamlit app via st.App(..., routes=[Mount("/bokeh", app=bokeh_app)]). When I serve the st.App with uvicorn.run(app), the mounted app works: the Bokeh page renders and its websocket callbacks run. When I start the same object with app.run(), the mounted route returns a blank white page.

Is mounting ASGI sub-applications via routes meant to be supported by App.run() and by streamlit run for st.App scripts? The App.run() docstring says it "reuses the same embedded ASGI server runner that streamlit run uses for st.App scripts".

The reason I am asking is that Streamlit Community Cloud launches apps with streamlit run, so I cannot use uvicorn.run(app) there. I would like a uniform Streamlit app for both the online and the offline installation.

Minimal reproducible example

page.py

import streamlit as st

st.write("Embedded Bokeh app below:")
st.iframe("/bokeh/app", height=300)

app.py

import sys

import streamlit as st
from starlette.routing import Mount
from bokeh.models import Div
from bokeh.server.asgi import BokehASGI


def bkapp(doc):
    doc.add_root(Div(text="Hello from Bokeh"))


bokeh_app = BokehASGI({"/app": bkapp})
app = st.App("page.py", routes=[Mount("/bokeh", app=bokeh_app)])

if __name__ == "__main__":
    if "--uvicorn" in sys.argv:
        import uvicorn
        uvicorn.run(app, host="localhost", port=8501)   # works
    else:
        app.run()                                       # mounted route is blank

Steps to reproduce

  1. python app.py --uvicorn and open http://localhost:8501/bokeh/app: "Hello from Bokeh" is shown, and the iframe in the Streamlit page also shows it.
  2. python app.py and open the same URL: blank white page, and the iframe in the Streamlit page is empty.

Expected behaviour

app.run() serves the routes passed to st.App(routes=...), including mounted ASGI apps with websockets, the same way uvicorn.run(app) does. I'd expect the same behaviour with streamlit run app.py.

Additional information

  • No errors in the terminal.

Environment

  • Streamlit: 1.65.0
  • Bokeh: 3.10.0
  • Python: 3.13
  • OS: Linux
  • Browser: Firefox

Thanks a lot for any advice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions