Reverse-proxying: Flask app with Bokeh server on Nginx

J K cas.xyz at googlemail.com
Mon May 15 09:59:27 UTC 2017


>
> Message: 4
> Date: Fri, 12 May 2017 18:26:39 +0300
> From: "Reinis Rozitis" <r at roze.lv>
> To: <nginx at nginx.org>
> Subject: Re: Re:Reverse-proxying: Flask app with Bokeh server on Nginx
> Message-ID: <437D05EFD1A24D9292CCE7BE45B2127C at Neiroze>
> Content-Type: text/plain; format=flowed; charset="UTF-8";
>         reply-type=original
>
> >  3. in the Flask app, I changed the URL
> > to:url='https://138.197.132.46:5006/bokeh/'
> > Now, when I open the app in the browser I get a 502 Bad Gateway, and the
> > Flask log file says the following:
> > raise IOError("Cannot pull session document because we failed to connect
> > to the server (to start the server, try the 'bokeh serve' command)")
>
> Well seems that the Flask app uses the url also for background requests.
>
> You can't mix 'https://' and :5006 port  in same url - this way the
> request
> goes to port 5006 but it expects to be also encrypted but if I understand
> correctly bokeh doesn't support SSL.
>
>
> p.s. for best performance you could tweak that the Flask->bokeh requests go
> through http but for the html template/output sent to clients there is
> another variable or relative paths.
>
>
> rr
>
>
>
> ------------------------------
>
> Message: 5
> Date: Fri, 12 May 2017 18:33:47 +0300
> From: "Reinis Rozitis" <r at roze.lv>
> To: <nginx at nginx.org>
> Subject: Re: Re:Reverse-proxying: Flask app with Bokeh server on Nginx
> Message-ID: <24A35BED74E7436B9515F58950D01034 at Neiroze>
> Content-Type: text/plain; format=flowed; charset="UTF-8";
>         reply-type=original
>
> What I forgot to add you need to change the 'url' (note the domain part)
> to:
>
> url='https://yourdomain/bokeh/'
>
> by looking at your error messages it seems that the 'url' is also directly
> used for client requests (probably placed in the html templated) - which
> means you can't use plain IP because then the browser most likely will just
> generate a SSL certificate and domain mismatch.
>
>
> rr
>


Thanks for answering again.

I followed your advise and change the Flask app script so that I have one
URL to pull the Bokeh session and another one to create the HTML script:

def company_abc():

url='http://127.0.0.1:5006/bokeh'

session=pull_session(url=url,app_path="/company_abc")

url_https='https://www.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)


This, however, results in the following error in Chrome:

GET
https://www.geomorphix.net/geomorphix/autoload.js?bokeh-autoload-element=dd
…6035f61fef5e&bokeh-session-id=hLR9QX79ofSg4yu7DZb1oHFdT14Ai7EcVCyh1iArcBf5


There's no other explanation. Both, Flask and Bokeh, log files don't
contain error messages.


>
>

> ------------------------------
>
> Message: 6
> Date: Fri, 12 May 2017 21:46:30 +0100
> From: Francis Daly <francis at daoine.org>
> To: J K via nginx <nginx at nginx.org>
> Cc: J K <cas.xyz at googlemail.com>
> Subject: Re: Reverse-proxying: Flask app with Bokeh server on Nginx
> Message-ID: <20170512204630.GC10157 at daoine.org>
> Content-Type: text/plain; charset=us-ascii
>
> On Fri, May 12, 2017 at 04:28:12PM +0200, J K via nginx wrote:
>
> Hi there,
>
> > > location /bokeh/ {
> > >     proxy_pass http://127.0.1.1:5006;
> > >
> > >     # .. with the rest of directives
> > > }
> > >
> > > relaunch the Bokeh app with
> > >
> > > --prefix=/bokeh/
> > >
> > > and (if takes part in the url construction rather than application
> > > background requests) change the url variable in the Flask app
> > >
> > > url='http://###.###.###.##:5006'
> > > to
> > > url='https://yourserver/bokeh/'
>
> > 1. in '/etc/nginx/sites-available/default' I added a new location as
> follow:
> >
> > location /bokeh/ {
> >
> >                    proxy_pass http://127.0.0.1:5006;  # you suggested
> 127.0.
> > *1*.1, but I figured that was a typo
>
> The proxy_pass address should be wherever your "bokeh" http server is
> actually listening.
>
> Which probably means that whatever you use up there...
>
> > command=/opt/envs/virtual/bin/bokeh serve company_abc.py company_xyz.py
> > geomorphix.py --prefix=/bokeh/ --allow-websocket-origin=www.example.com
> > --allow-websocket-origin=example.com --host=138.197.132.46:5006
> > --use-xheaders
>
> you should also use up there as --host.
>
> I suspect that making them both be 127.0.0.1 will be the easiest
> way of reverse-proxying things; but I also suspect that the
> "--allow-websocket-origin" part suggests that you may want to configure
> nginx to reverse proxy the web socket connection too. Notes are at
> http://nginx.org/en/docs/http/websocket.html
>
> It will be helpful to have a very clear picture of what talks to what,
> when things are working normally; that should make it easier to be
> confident that the same links are in place with nginx in the mix.
>
>
Hi Francis,

Thanks for your answer!

As you suggested, I did the following:

1. in '/etc/supervisor/conf.d/bokeh_serve.conf' I changed the host to
127.0.0.1:

[program:bokeh_serve]

command=/opt/envs/virtual/bin/bokeh serve company_abc.py --prefix=/bokeh/
--allow-websocket-origin=www.example.com --allow-websocket-origin=
example.com --host=127.0.0.1:5006 <http://138.197.132.46:5006/>
 --use-xheaders

directory=/opt/webapps/flask_telemetry

autostart=false

autorestart=true

startretries=3
user=nobody

2. I configure nginx to reverse proxy the web socket connection by adding
the following lines to each location block in '/etc/nginx/sites-available/
default':

proxy_http_version 1.1;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

3. In the Flask web app code I changed the URL of the route accordingly to
127.0.0.1:

@app.route("/company_abc/")

@login_required

@roles_accepted('company_abc', 'admin')

def geomorphix():

    url='http://127.0.0.1:5006/bokeh'

    session=pull_session(url=url,app_path="/company_abc")

    bokeh_script=autoload_server(None,app_path="/geomorphix",session_id=
session.id,url=url)

    return render_template("geomorphix.html", bokeh_script=bokeh_script)


When I enter the website with the Bokeh script in my browser, I get a
connection refused error:

GET http://127.0.0.1:5006/bokeh/example/autoload.js?bokeh-autoload-element=…
9cf799610fb8&bokeh-session-id=8tvMFfJwtVFccTctGHIRPPsT3h6IF6nUFkJ8l6ZQALXl
net::ERR_CONNECTION_REFUSED

Looking at the log file of the Bokeh server, everything seems to be fine:

2017-05-15 08:56:19,267 Starting Bokeh server version 0.12.4
2017-05-15 08:56:19,276 Starting Bokeh server on port 5006 with
applications at paths ['/company_abc']
2017-05-15 08:56:19,276 Starting Bokeh server with process id: 28771
2017-05-15 08:56:24,530 WebSocket connection opened
2017-05-15 08:56:25,304 ServerConnection created

Also the Flask log file shows no error:

[2017-05-15 08:56:13 +0000] [28760] [INFO] Starting gunicorn 19.6.0
[2017-05-15 08:56:13 +0000] [28760] [INFO] Listening at: http://0.0.0.0:8118
 (28760)
[2017-05-15 08:56:13 +0000] [28760] [INFO] Using worker: sync
[2017-05-15 08:56:13 +0000] [28765] [INFO] Booting worker with pid: 28765



The Nginx error log '/var/log/nginx/flask/error.log' is empty.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20170515/b1a35180/attachment-0001.html>


More information about the nginx mailing list