How to integrate a Panel app with FastAPI on the same port

Hi all, I’m using FastAPI framework as my main application and I want to integrate panel application with it in the same port. For eg, If my main (FastAPI) application runs in port 8000, the Panel application also should run on 8000. Because I hosted my main (FastAPI) application in Azure App services which enables 80 and 443 by default. I can not add a new port to that.

I use this command to start my main(FastAPI) application - poetry run uvicorn app.main:app --reload

Whenever I click on Panel application menu (from base.html), it should render panel application in the same port.

pl_serv.py

plot_app = FastAPI()

# Middleware to handle trusted hosts
plot_app.add_middleware(TrustedHostMiddleware, allowed_hosts=["# Respective hosts"])

def create_app():
    pn.extension("bokeh")
    pn.extension("tabulator")

    data = # from source
    return create_panel(data, standalone_app=False).servable()

# Serve the Panel app using WSGIMiddleware
panel_app = pn.serve(
    {"/app": create_app},
    allow_websocket_origin=["Respective origins"],
    address="0.0.0.0",
    port=0,  # Use port 0 to avoid binding to a specific port
    show=False,
    threaded=True,
    static_dirs={"assets": "path to static")},
)

plot_app.mount("/panel", WSGIMiddleware(panel_app))

@plot_app.get("/panel")
async def panel_page(request: Request):
    return RedirectResponse(url="/panel/app")

@plot_app.get("/plot")
async def plot_page(request: Request):
    try:
        script = server_document(f"http://{request.url.hostname}/panel/app")
        return templates.TemplateResponse(request, "pl.html", {"script": script})
    except Exception:
        return templates.TemplateResponse(request, "error.html", {"error": "Could not load plot page."})

@plot_app.get("/logout")
async def logout():
    return RedirectResponse(url="/")

@plot_app.get("/")
async def main_app():
    return RedirectResponse(url="/panel/plot")

main(FastAPI) application - main.py:

from fastapi import FastAPI
from app.ui.plot_service import plot_app

app = FastAPI()

# Mount the plot_app to serve the Panel application
app.mount("/panel", plot_app)

# Other routes and middleware configurations...

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Application</title>
    <link rel="stylesheet" href="/static/styles.css">
</head>
<body>
    <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/panel">Panel application</a></li>
            <!-- Other menu items -->
        </ul>
    </nav>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

pl.html

{% extends "base.html" %}
<head>
{% block title %}Renewable{% endblock %}
</head>

{% block extra_script %}
    {{ script|safe }}
{% endblock %}

Despite these changes, I am still getting the following error:

Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/panel/app/autoload.js?bokeh-autoload-element=e9d9f7a5-a22f-4170-8f3a-32c59e1c72f3&bokeh-app-path=/panel/app&bokeh-absolute-url=http://localhost/panel/app

How can I resolve this issue and serve the Panel app on the same port as the FastAPI app without encountering the net::ERR_CONNECTION_REFUSED error?

Is this relevant? Availabe now in the Panel 1.5 RC.

https://holoviz-dev.github.io/panel/how_to/integrations/FastAPI.html

I have followed this link and installed RC1 version of Panel. I could be able to render the Panel application on the same port as my main FastAPI application. But whenever I click some toggles (Widgets) it is not updating the plots based on that toggle selection, also I’m getting this below error in my terminal.

WARNING: panel.io.document - Failed sending message due to following error: cannot unpack non-iterable Buffer object

Could you file an issue with a minimal example?

The issue is fixed here and will be released in the next dev release.

Is there a missing Github link in your post @philippjfr ? Is it this one? Add FastAPI based serve functions by philippjfr · Pull Request #7205 · holoviz/panel · GitHub

Panel 1.5.0 is now released and the guide is here Running Panel apps in FastAPI.

@Marc this issue occurs for the user when using the current 1.5 release. Do you know what fix @philippjfr is referring to? It seems to refer to a post-1.5 fix? But there is no link.

See link with details, code and screen recording below. @salman , could you post the details and code over here please, as requested by @ahuang11 ?

Yeah sure.

I have created sample project and pushed to my github account.

Project link - GitHub - salmantec/panel_fastapi_integration

Code explanation:

You can find two files called panel_app_v144.py and panel_app_v150.py under backend/apis/general_pages folder. I’ve created these two different .py files based on Panel version to show you the issue I’m facing.

Also, In main.py file I’ve commented few lines with this command (Enable below line for panel_app_v150.py ). enable those lines under this command to test the panel_app_v150.py .

Before testing panel_app_v144.py, please go to requirements.txt file and make below changes

  1. Comment bokeh-fastapi library
  2. Downgrade panel library version to 1.4.4
  3. Downgrade bokeh library version to 3.4.0
  4. Run pip3 install -r requirements.txt

Before testing panel_app_v150.py, again go to requirements.txt file and make below changes

  1. Uncomment bokeh-fastapi library
  2. Upgrade panel library version to 1.5.0
  3. Upgrade bokeh library version to 3.5.2
  4. Run pip3 install -r requirements.txt

NOTE: To start the application, please use uvicorn main:app --reload command from backend folder.

Testing in web

I couldn’t upload attachments here in this discourse, getting this error message - Sorry, new users can not upload attachments.
So, I’ve attached two screen recording files with proper filename to map with panel library version in the discord general chat.

If you see in panel_app_v144.py file, I’ve used separate port (5123) to render the Panel application and it worked well, you could see that in Panel version 1.4.4 recording, I can able to do interactivity like If I click left side selectors, It will update the right side plot line graph.

But in panel_app_v150.py file, I have not used separate port and I tried to use same fastapi application port for panel application too (based on the latest documentation - used from panel.io.fastapi import add_application ). It didn’t work as expected like the interactivity didn’t work You can see that in Panel version 1.5.0 recording, that interactivity is not working.

Please check and let me know whether I’m making mistake in this scenario or we have to fix it in the library for this scenario.

@philippjfr , @Marc

You have to use the released version of bokeh-fastapi 0.1.0 and not an old dev release.

Thanks for pointing it out @philippjfr. Getting this warning in my terminal while running it

GET /static/js/bokeh-widgets.min.js?v=a9b89524d45c9917073e9a3e35c284447f993ef108f68d4609e2b4618a4a2310af427b818b53f467ff1ece8714c2f0e8ad8f3e76361f410e292253bd271199d8 HTTP/1.1” 404 Not Found

GET /static/js/bokeh-tables.min.js?v=fbbe15922c8405a08cc90e24b24fb8e2339900a06a31f2dc8263235cd50ea70b731c2b09f7e07d7e7460065bdb7c32d0b9a1301c9b302846688b542b8db17f6d HTTP/1.1” 404 Not Found

GET /static/extensions/panel/panel.min.js?v=1f4dc096d58f7d21e3875671aee6f29b120ab84218fa47db2cb53bc9eb5b4dac HTTP/1.1” 404 Not Found

Should we need to add any cdn links in base.html ?

@salman I’m not sure what you’re trying tbh. Using the commented out Panel 1.5.0 approach in your repo I did not see any such warnings and no base.html should be needed in the first place.

Related: Fix handling of binary buffers by philippjfr · Pull Request #18 · bokeh/bokeh-fastapi · GitHub

Never mind, fixed it. Actually, I used pn.extension("bokeh") in wrong place. It started working after removing this line.