Hi @_jm, thanks for posting this answer. It is really very helpful.
I tried to follow all your instructions above, but I am running into an Internal Server error for my Flask app
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
Here are the full details of my setup based on your instructions
Flask App
In my Flask app’s main.py
, I followed your earlier post in this thread to construct PANEL_URL
# main.py
# <bokeh-server-name> = mybserverapp # name of Bokeh server standalone script
# <bokeh-app-name> = mybokehserverapp # name of Heroku app for Bokeh Server
# <masked-app-name> = mydemoflaskapp # name of Heroku app for Flask+Gunicorn
PANEL_URL = "https://mydemoflaskapp.herokuapp.com"
BOKEH_URL = "https://mybokehserverapp.herokuapp.com/mybserverapp"
In my Flask app’s Procfile
, I have
web: gunicorn main:app
In my templates/embed.html
, I have this content
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Embedding a Bokeh Server</title>
</head>
<body>
<div>
This Bokeh app.
</div>
{{ script|safe }}
</body>
</html>
For the Flask app, my requirements.txt
contains
bokeh
flask
gunicorn
This app on heroku is named mydemoflaskapp
.
The directory structure for this Flask app is as follows
├── main.py
├── Procfile
├── requirements.txt
└── templates
└── embed.html
Bokeh App
In my Bokeh Server app I have the following contents
# mybserverapp.py
from bokeh.layouts import column
from bokeh.plotting import curdoc, figure
from bokeh.themes import Theme
fruits = ["Apples", "Pears", "Nectarines", "Plums", "Grapes", "Strawberries"]
counts = [5, 3, 4, 2, 4, 6]
p = figure(
x_range=fruits,
plot_height=250,
title="Fruit Counts",
toolbar_location=None,
tools="",
)
p.vbar(x=fruits, top=counts, width=0.9)
p.xgrid.grid_line_color = None
p.y_range.start = 0
curdoc().add_root(column(p))
curdoc().theme = Theme(filename="theme.yaml")
My Bokeh app’s theme.yaml
contains
attrs:
Figure:
background_fill_color: "#ffffff"
outline_line_color: white
toolbar_location: above
height: 500
width: 800
Grid:
grid_line_dash: [6, 4]
grid_line_color: white
Per your recommendation, in my bokeh app’s Procfile
I have replaced <flask-app-name>
by the name of my Flask app on Heroku (mydemoflaskapp
) and I have replaced <bokeh-server-name>
by the name of my Bokeh server script (mybserverapp
)
web: bokeh serve --address="0.0.0.0" --port=$PORT mybserverapp.py --allow-websocket-origin=mydemoflaskapp.herokuapp.com
For this Bokeh app, my requirements.txt
contains
bokeh
This app on heroku is named mybokehserverapp
.
The directory structure for my Bokeh server app is as follows
├── mybserverapp.py
├── Procfile
├── requirements.txt
└── theme.yaml
The logs on my Flask app shows the following
2021-02-20T19:15:12.747347+00:00 heroku[web.1]: Starting process with command `gunicorn main:app`
2021-02-20T19:15:15.476758+00:00 app[web.1]: [2021-02-20 19:15:15 +0000] [4] [INFO] Starting gunicorn 20.0.4
2021-02-20T19:15:15.477519+00:00 app[web.1]: [2021-02-20 19:15:15 +0000] [4] [INFO] Listening at: http://0.0.0.0:12639 (4)
2021-02-20T19:15:15.477646+00:00 app[web.1]: [2021-02-20 19:15:15 +0000] [4] [INFO] Using worker: sync
2021-02-20T19:15:15.482372+00:00 app[web.1]: [2021-02-20 19:15:15 +0000] [9] [INFO] Booting worker with pid: 9
2021-02-20T19:15:15.553524+00:00 app[web.1]: [2021-02-20 19:15:15 +0000] [10] [INFO] Booting worker with pid: 10
2021-02-20T19:15:16.142507+00:00 heroku[web.1]: State changed from starting to up
2021-02-20T19:15:21.000000+00:00 app[api]: Build succeeded
2021-02-20T19:29:31.568283+00:00 heroku[router]: at=info method=GET path="/" host=mydemoflaskapp.herokuapp.com request_id=<removed> fwd="<ip-address-removed>" dyno=web.1 connect=1ms service=230ms status=500 bytes=470 protocol=https
2021-02-20T19:29:31.559310+00:00 app[web.1]: <internal-ip-address-removed-10.33.....> - - [20/Feb/2021:19:29:31 +0000] "GET /ws HTTP/1.1" 404 232 "-" "Tornado/6.1"
2021-02-20T19:29:31.566731+00:00 app[web.1]: ERROR:main:Exception on / [GET]
2021-02-20T19:29:31.566732+00:00 app[web.1]: Traceback (most recent call last):
2021-02-20T19:29:31.566732+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 2447, in wsgi_app
2021-02-20T19:29:31.566733+00:00 app[web.1]: response = self.full_dispatch_request()
2021-02-20T19:29:31.566733+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1952, in full_dispatch_request
2021-02-20T19:29:31.566733+00:00 app[web.1]: rv = self.handle_user_exception(e)
2021-02-20T19:29:31.566734+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1821, in handle_user_exception
2021-02-20T19:29:31.566734+00:00 app[web.1]: reraise(exc_type, exc_value, tb)
2021-02-20T19:29:31.566734+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
2021-02-20T19:29:31.566735+00:00 app[web.1]: raise value
2021-02-20T19:29:31.566735+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1950, in full_dispatch_request
2021-02-20T19:29:31.566735+00:00 app[web.1]: rv = self.dispatch_request()
2021-02-20T19:29:31.566736+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1936, in dispatch_request
2021-02-20T19:29:31.566737+00:00 app[web.1]: return self.view_functions[rule.endpoint](**req.view_args)
2021-02-20T19:29:31.566737+00:00 app[web.1]: File "/app/main.py", line 22, in bkapp_page
2021-02-20T19:29:31.566738+00:00 app[web.1]: with pull_session(url=PANEL_URL) as session:
2021-02-20T19:29:31.566738+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/bokeh/client/session.py", line 120, in pull_session
2021-02-20T19:29:31.566738+00:00 app[web.1]: session.pull()
2021-02-20T19:29:31.566738+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/bokeh/client/session.py", line 381, in pull
2021-02-20T19:29:31.566738+00:00 app[web.1]: self.check_connection_errors()
2021-02-20T19:29:31.566739+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/bokeh/client/session.py", line 367, in check_connection_errors
2021-02-20T19:29:31.566740+00:00 app[web.1]: raise OSError(f"Check your application path! The given Path is not valid: {self.url}")
2021-02-20T19:29:31.566743+00:00 app[web.1]: OSError: Check your application path! The given Path is not valid: wss://mydemoflaskapp.herokuapp.com/ws
This seems to be point to a problem with PANEL_URL
, although I am not sure if this is the only problem.
When I try to load this app at https://mydemoflaskapp.herokuapp.com
, I get the following Internal Server Error message
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
For my Bokeh app, the logs are
2021-02-20T19:11:05.371641+00:00 heroku[web.1]: Starting process with command `bokeh serve --address="0.0.0.0" --port=8750 mybserverapp.py --allow-websocket-origin=myflaskapp.herokuapp.com`
2021-02-20T19:11:11.000000+00:00 app[api]: Build succeeded
2021-02-20T19:11:12.388893+00:00 app[web.1]: 2021-02-20 19:11:12,388 Starting Bokeh server version 2.2.3 (running on Tornado 6.1)
2021-02-20T19:11:12.429012+00:00 app[web.1]: 2021-02-20 19:11:12,428 User authentication hooks NOT provided (default user enabled)
2021-02-20T19:11:12.491265+00:00 app[web.1]: 2021-02-20 19:11:12,491 Bokeh app running at: http://0.0.0.0:8750/mybserverapp
2021-02-20T19:11:12.497738+00:00 app[web.1]: 2021-02-20 19:11:12,497 Starting Bokeh server with process id: 4
2021-02-20T19:11:12.646429+00:00 heroku[web.1]: State changed from starting to up
2021-02-20T19:45:23.401735+00:00 heroku[router]: at=info method=GET path="/" host=mybokehserverapp.herokuapp.com request_id=e500b6b1-6796-41b2-9f48-81640b839e33 fwd="<ip-address-removed>" dyno=web.1 connect=1ms service=4ms status=302 bytes=189 protocol=https
2021-02-20T19:45:23.809813+00:00 heroku[router]: at=info method=GET path="/mybserverapp" host=mybokehserverapp.herokuapp.com request_id=<removed> fwd="<ip-address-removed>" dyno=web.1 connect=1ms service=373ms status=200 bytes=4089 protocol=https
2021-02-20T19:45:23.928461+00:00 heroku[router]: at=info method=GET path="/static/js/bokeh.min.js?v=<removed>" host=mybokehserverapp.herokuapp.com request_id=e5d9dc98-a17c-4f8e-af0b-5ad257ffda87 fwd="<ip-address-removed>" dyno=web.1 connect=1ms service=56ms status=200 bytes=771696 protocol=https
2021-02-20T19:45:23.943559+00:00 heroku[router]: at=info method=GET path="/static/js/bokeh-widgets.min.js?v=<removed>" host=mybokehserverapp.herokuapp.com request_id=8d98210a-8679-4f4b-8ca1-cce4645aff53 fwd="<ip-address-removed>" dyno=web.1 connect=0ms service=19ms status=200 bytes=261012 protocol=https
2021-02-20T19:45:23.949794+00:00 heroku[router]: at=info method=GET path="/static/js/bokeh-tables.min.js?v=<removed>" host=mybokehserverapp.herokuapp.com request_id=9fdcb970-b335-4872-a315-85df30044ebd fwd="<ip-address-removed>" dyno=web.1 connect=1ms service=19ms status=200 bytes=296650 protocol=https
2021-02-20T19:45:24.198892+00:00 app[web.1]: 2021-02-20 19:45:24,198 404 GET /favicon.ico (10.99.209.116) 3.73ms
2021-02-20T19:45:24.199452+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=mybokehserverapp.herokuapp.com request_id=af5a01ec-2ce3-4fb0-b86f-0c5f777f8e58 fwd="<ip-address-removed>" dyno=web.1 connect=1ms service=6ms status=404 bytes=238 protocol=https
2021-02-20T19:45:24.289261+00:00 app[web.1]: 2021-02-20 19:45:24,289 Refusing websocket connection from Origin 'https://mybokehserverapp.herokuapp.com'; use --allow-websocket-origin=mybokehserverapp.herokuapp.com or set BOKEH_ALLOW_WS_ORIGIN=mybokehserverapp.herokuapp.com to permit this; currently we allow origins {'myflaskapp.herokuapp.com:80'}
2021-02-20T19:45:24.294237+00:00 app[web.1]: 2021-02-20 19:45:24,294 403 GET /mybserverapp/ws (<internal-ip-address-removed-10.97.....>) 5.91ms
When I try to load this app at https://mybokehserverapp.herokuapp.com
, I get a blank page.
Questions
- Could you confirm that the following were correctly assigned, based on your recommendations in the above answer
# main.py
# <bokeh-server-name> = mybserverapp # name of Bokeh server standalone script
# <bokeh-app-name> = mybokehserverapp # name of Heroku app for Bokeh Server
# <masked-app-name> = mydemoflaskapp # name of Heroku app for Flask+Gunicorn
- Per your above answer, do you detect any other problems with my implementation of your suggestion?