Reverse-proxying: Flask app with Bokeh server on Nginx

Francis Daly francis at daoine.org
Wed May 17 23:14:14 UTC 2017


On Wed, May 17, 2017 at 12:34:17PM +0200, J K via nginx wrote:

Hi there,

> Initially, without https, everything was running well.

Yes.

> I was deploying a
> Bokeh server with the 'company_abc' app, and used a Flask app to render the
> website and handle login/redirecting/etc.

Yes.

> Everything was behind a Nginx server.

No.

Your bokeh server was not behind nginx.

Your bokeh server always listened on port 5006. Your nginx config did
not proxy_pass to port 5006. Your web clients connected directly to
bokeh on port 5006, not going through nginx.


If you go back to the beginning, and configure flask behind nginx
according to the flask documentation (as you had done); and configure
bokeh behind nginx according to the bokeh documentation that you showed,
then you may find that it all Just Works.

Right now, you have an inconsistent mix of configurations.

What you want is that whenever the client browser talks to flask,
it uses a url prefix like https://www.example.comw/flask/, and
whenever the client browser talks to bokeh, it uses a url prefix like
https://www.example.com/bokeh/.

When flask talks to bokeh, it can use a url prefix
like http://127.0.0.1:5006/bokeh/. Or it can use
https://www.example.com/bokeh/. It is probably better if it uses the
first one.


> The script tag looks like this:
> 
> <script
> 
> src="https://example.com/company_abc/autoload.js?bokeh-
> autoload-element=c5c9bdb5-40e8-46a2-9bf0-40a9d396ce97"
> id="c5c9bdb5-40e8-46a2-9bf0-40a9d396ce97"

Ok, so that gets the client browser to make a request like
https://example.com/company_abc/. You want that to be proxy_pass'ed to
the bokeh server. Does your nginx config say to do that?

> Now, when the browser opens the 'company_abc.html' page it sends a request
> to the Nginx server. This should then proxy to the Bokeh server.
> Does this sound correct?

What is the company_abc.html page?

If it matters, give the full url. Possibly it does not matter here.

> Now, I have done some changes and get a different error. The Bokeh app I'm
> starting now with
> 
> bokeh serve company_abc.py --allow-websocket-origin=example.com
>  --allow-websocket-origin=www.example.com --port=5006 \
> --host="*" --use-xheaders

The bokeh documentation you linked to previously uses many fewer arguments.

> So, it's running on localhost, port 5006. In the Flask app I redefined the
> route to the app as follows:
> 
> @app.route("/company_abc/")
> def company_abc():
>     url='http://127.0.0.1:5006/'
>     session=pull_session(url=url,app_path="/company_abc")
>     url_https='https://example.com/'
>     bokeh_script=autoload_server(None,app_path="/company_abc/",session_id=
> session.id,url=url_https)
>     return render_template("company_abc.html", bokeh_script=bokeh_script)

I think that the questions I asked about those various url fragments
have not been explicitly answered yet.

> For the Nginx config file I followed the template from the Bokeh User Guide
> <http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#reverse-proxying-with-nginx-and-ssl>
> :
> 
> location /company_abc/ {
>                   proxy_pass http://127.0.0.1:5006;
>                   proxy_set_header Upgrade $http_upgrade;
>                   proxy_set_header Connection "upgrade";
>                   proxy_http_version 1.1;
>                   proxy_set_header X-Forwarded-Proto $scheme;
>                   proxy_set_header X-Forwarded-For
> $proxy_add_x_forwarded_for;
>                   proxy_set_header Host $host:$server_port;
>                   proxy_buffering off;
>         }
> }
> 
> 
> Now, with these setting I get the following errors in Chrome:
> 
> GET https://example.com/static/css/bokeh.min.css?v=
> 7246afcfffc127faef7c138bce4742e9

What do you want nginx to do with that request?

What have you configured nginx to do with that request?

The request starts with /static/, not /company_abc/, so nginx will not
try to send it to the bokeh server.

> Interestingly, when I manually execute the lines
> 
> url='http://127.0.0.1:5006/'
> session=pull_session(url=url,app_path="/company_abc")
> url_https='https://example.com/'
> bokeh_script=autoload_server(None,app_path="/company_abc/",session_id=
> session.id,url=url_https)

What do you mean by "manually execute the lines"?

Is this a thing that you expect the client browser to do, or a thing
that you expect the flask server to do, or something else?

> The Bokeh log file says that a WebSocket is opened and a ServerConnection
> is created:
> 
> 2017-05-17 10:21:09,915 WebSocket connection opened
> 2017-05-17 10:21:10,769 ServerConnection created
> 
> 
> What does the new error mean?
> Why is a WebSocket opened and ServerConnection created only when I manually
> pull a session?

I am not seeing any nginx errors being shown here.

I suspect that if you can show one minimal complete configuration, and
show one request, and show the response that you get, and describe the
response that you want instead, then someone may be able to help you
find the next step.

At the moment, I'd say start again on a test system and follow one recipe
exactly; when you see things working, then you can start changing things
to better match the configuration that you want.

Good luck with it,

	f
-- 
Francis Daly        francis at daoine.org


More information about the nginx mailing list