<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><span style="font-size:12.8px">Hi Francis,</span><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Initially, without https, everything was running well. 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. Everything was behind a Nginx server. </div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Then, I installed https the Bokeh app would not be rendered on the website. The Flask app worked fine, as before.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">I think what's happening is that Nginx sends a request to the Flask app. Flask then pulls the Bokeh session with</div><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">session=<a href="http://bokeh.pydata.org/en/0.12.4/docs/reference/client.html#bokeh.client.session.pull_session" target="_blank">pull_session</a>(url=url,<wbr>app_path="/company_abc")</font></div><div><font face="monospace, monospace"><br></font></div></blockquote><font face="arial, helvetica, sans-serif" style="font-size:12.8px">and creates a script tag with </font><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">bokeh_script=<a href="http://bokeh.pydata.org/en/latest/docs/reference/embed.html#bokeh.embed.autoload_server" target="_blank">autoload_server</a>(<wbr>None,app_path="/company_abc/",<wbr>session_id=<a href="http://session.id/" target="_blank">session.id</a>,url=url_<wbr>https)<br></font></div><div><font face="monospace, monospace"><br></font></div></blockquote><font face="arial, helvetica, sans-serif" style="font-size:12.8px">That's then embedded into the html page by</font><span class="gmail-im" style="font-size:12.8px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">return render_template("company_abc.<wbr>html", bokeh_script=bokeh_script)<br></font></div><div><font face="monospace, monospace"><br></font></div></blockquote></span><div style="font-size:12.8px">The script tag looks like this:</div><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace, monospace"><script<br></font></blockquote><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote></blockquote><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span style="font-family:monospace,monospace">src="<a href="https://example.com/company_abc/autoload.js?bokeh-autoload-element=c5c9bdb5-40e8-46a2-9bf0-40a9d396ce97" target="_blank">https://example.com/<wbr>company_abc/autoload.js?bokeh-<wbr>autoload-element=c5c9bdb5-<wbr>40e8-46a2-9bf0-40a9d396ce97</a>" id="c5c9bdb5-40e8-46a2-9bf0-<wbr>40a9d396ce97"</span></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span style="font-family:monospace,monospace">data-bokeh-model-id=""</span></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span style="font-family:monospace,monospace">data-bokeh-doc-id=""</span></blockquote></blockquote><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><font face="monospace, monospace">></script><br></font><br></blockquote><span style="font-size:12.8px;font-family:arial,helvetica,sans-serif">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.</span><br style="font-size:12.8px"><div style="font-size:12.8px">Does this sound correct?</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Now, I have done some changes and get a different error. The Bokeh app I'm starting now with  <br></div><div style="font-size:12.8px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">bokeh serve company_abc.py --allow-websocket-origin=<a href="http://example.com/" target="_blank">examp<wbr>le.com</a> --allow-websocket-origin=<a href="http://www.example.com/" target="_blank">www.<wbr>example.com</a> --port=5006 \</font></div><div><font face="monospace, monospace">--host="*" --use-xheaders</font><br></div></blockquote><font face="arial, helvetica, sans-serif"><br></font></div><div style="font-size:12.8px"><font face="arial, helvetica, sans-serif">So, it's running on localhost, port 5006. In the Flask app I redefined the route to the app as follows:</font></div><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">@app.route("/company_abc/")</font></div><div><span style="font-family:monospace,monospace">def company_abc():</span><br></div><div><font face="monospace, monospace">    url='<a href="http://127.0.0.1:5006/" target="_blank">http://127.0.0.1:5006/</a>'</font></div><div><font face="monospace, monospace">    session=pull_session(url=url,<wbr>app_path="/company_abc")</font></div><div><font face="monospace, monospace">    url_https='<a href="https://example.com/" target="_blank">https://example.<wbr>com/</a>'</font></div><div><font face="monospace, monospace">    bokeh_script=autoload_server(<wbr>None,app_path="/</font><span style="font-family:monospace,monospace">company_abc</span><font face="monospace, monospace">/",<wbr>session_id=<a href="http://session.id/" target="_blank">session.id</a>,url=url_<wbr>https)</font></div><span class="gmail-im"><font face="monospace, monospace">    return render_template("</font><span style="font-family:monospace,monospace">company_abc</span><font face="monospace, monospace">.<wbr>html", bokeh_script=bokeh_script)</font></span></blockquote><font face="monospace, monospace" style="font-size:12.8px"><br></font><div style="font-size:12.8px"><font face="arial, helvetica, sans-serif">For the Nginx config file I followed the <a href="http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#reverse-proxying-with-nginx-and-ssl" target="_blank">template from the Bokeh User Guide</a>:</font></div><div style="font-size:12.8px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">location /company_abc/ {</font></div><div><font face="monospace, monospace">                  proxy_pass <a href="http://127.0.0.1:5006/" target="_blank">http://127.0.0.1:5006</a>;</font></div><span class="gmail-im"><div><font face="monospace, monospace">                  proxy_set_header Upgrade $http_upgrade;</font></div><div><font face="monospace, monospace">                  proxy_set_header Connection "upgrade";</font></div></span><div><font face="monospace, monospace">                  proxy_http_version 1.1;</font></div><div><font face="monospace, monospace">                  proxy_set_header X-Forwarded-Proto $scheme;</font></div><div><font face="monospace, monospace">                  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</font></div><div><font face="monospace, monospace">                  proxy_set_header Host $host:$server_port;</font></div><div><font face="monospace, monospace">                  proxy_buffering off;</font></div><div><font face="monospace, monospace">        }</font></div><div><font face="monospace, monospace">}</font></div></blockquote><br></div><div style="font-size:12.8px"><font face="arial, helvetica, sans-serif">Now, with these setting I get the following errors in Chrome:</font></div><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">GET <a href="https://example.com/static/css/bokeh.min.css?v=7246afcfffc127faef7c138bce4742e9" target="_blank">https://example.com/static/<wbr>css/bokeh.min.css?v=<wbr>7246afcfffc127faef7c138bce4742<wbr>e9</a> </font></div><div><div><font face="monospace, monospace"><a href="http://example.com/:9" target="_blank">example.com/:9</a> </font></div><div><font face="monospace, monospace">GET <a href="https://example.com/static/css/bokeh-widgets.min.css?v=d9cb9322d940f107727b091ff98d9c70" target="_blank">https://example.com/static/<wbr>css/bokeh-widgets.min.css?v=<wbr>d9cb9322d940f107727b091ff98d9c<wbr>70</a> </font></div></div><div><div><font face="monospace, monospace"><a href="http://example.com/:12" target="_blank">example.com/:12</a> </font></div><div><font face="monospace, monospace">GET <a href="https://example.com/static/js/bokeh-widgets.min.js?v=1af1302b8bd7fcc88c7bcafb8771497b" target="_blank">https://example.com/static/js/<wbr>bokeh-widgets.min.js?v=<wbr>1af1302b8bd7fcc88c7bcafb877149<wbr>7b</a> </font></div></div><div><div><font face="monospace, monospace"><a href="http://example.com/:11" target="_blank">example.com/:11</a> </font></div><div><font face="monospace, monospace">GET <a href="https://example.com/static/js/bokeh.min.js?v=9d3af13f493d36073a89714f6a5240c6" target="_blank">https://example.com/static/js/<wbr>bokeh.min.js?v=<wbr>9d3af13f493d36073a89714f6a5240<wbr>c6</a> </font></div></div><div><div><font face="monospace, monospace"><a href="http://example.com/:12" target="_blank">example.com/:12</a> </font></div><div><font face="monospace, monospace">GET <a href="https://example.com/static/js/bokeh-widgets.min.js?v=1af1302b8bd7fcc88c7bcafb8771497b" target="_blank">https://example.com/static/js/<wbr>bokeh-widgets.min.js?v=<wbr>1af1302b8bd7fcc88c7bcafb877149<wbr>7b</a> 404 (NOT FOUND)</font></div></div><div><font face="monospace, monospace">(index):14 Uncaught ReferenceError: Bokeh is not defined</font></div><div><font face="monospace, monospace">    at (index):14</font></div><div><font face="monospace, monospace">(anonymous) @ (index):14</font></div><div><font face="monospace, monospace">(index):37 Uncaught ReferenceError: Bokeh is not defined</font></div><div><font face="monospace, monospace">    at HTMLDocument.fn ((index):37)</font></div></blockquote><font face="monospace, monospace" style="font-size:12.8px"><br></font><div style="font-size:12.8px"><font face="arial, helvetica, sans-serif">The log file for the Bokeh server shows no errors:</font></div><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace, monospace"><div>2017-05-17 10:17:49,640 Starting Bokeh server version 0.12.4</div><div>2017-05-17 10:17:49,641 Host wildcard '*' can expose the application to HTTP host header attacks. Host wildcard should only be used for testing purpose.</div><div>2017-05-17 10:17:49,647 Starting Bokeh server on port 5006 with applications at paths ['/geomorphix']</div><div>2017-05-17 10:17:49,647 Starting Bokeh server with process id: 15851</div><div>2017-05-17 10:18:08,829 200 GET /geomorphix/ (37.201.192.96) 845.69ms</div><div><br></div></font></blockquote><font face="arial, helvetica, sans-serif" style="font-size:12.8px">Interestingly, when I manually execute the lines</font><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace">url='<a href="http://127.0.0.1:5006/" target="_blank">http://127.0.0.1:5006/</a>'</font></div><div><font face="monospace, monospace">session=pull_session(url=url,<wbr>app_path="/company_abc")</font></div><div><font face="monospace, monospace">url_https='<a href="https://example.com/" target="_blank">https://example.<wbr>com/</a>'</font></div><div><font face="monospace, monospace">bokeh_script=autoload_server(<wbr>None,app_path="/</font><span style="font-family:monospace,monospace">company_abc</span><font face="monospace, monospace">/",<wbr>session_id=<a href="http://session.id/" target="_blank">session.id</a>,url=url_<wbr>https)</font></div></blockquote><font face="monospace, monospace" style="font-size:12.8px"><br></font><div style="font-size:12.8px"><font face="arial, helvetica, sans-serif">The Bokeh log file says that a WebSocket is opened and a ServerConnection is created:</font></div><blockquote style="font-size:12.8px;margin:0px 0px 0px 40px;border:none;padding:0px"><font face="monospace, monospace"><div>2017-05-17 10:21:09,915 WebSocket connection opened</div><div>2017-05-17 10:21:10,769 ServerConnection created</div></font></blockquote><font face="monospace, monospace" style="font-size:12.8px"><br></font><div style="font-size:12.8px"><font face="monospace, monospace">What does the new error mean?</font></div><div style="font-size:12.8px"><font face="monospace, monospace">Why is a WebSocket opened and ServerConnection created only when I manually pull a session?</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">Thanks!</font></div></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Message: 3<br>
Date: Tue, 16 May 2017 17:49:07 +0100<br>
From: Francis Daly <<a href="mailto:francis@daoine.org">francis@daoine.org</a>><br>
To: J K via nginx <<a href="mailto:nginx@nginx.org">nginx@nginx.org</a>><br>
Cc: J K <<a href="mailto:cas.xyz@googlemail.com">cas.xyz@googlemail.com</a>><br>
Subject: Re: Re :Re: Re:Reverse-proxying: Flask app with Bokeh server<br>
        on Nginx<br>
Message-ID: <<a href="mailto:20170516164907.GE10157@daoine.org">20170516164907.GE10157@<wbr>daoine.org</a>><br>
Content-Type: text/plain; charset=utf-8<br>
<br>
On Mon, May 15, 2017 at 11:59:27AM +0200, J K via nginx wrote:<br>
<br>
Hi there,<br>
<br>
To recap:<br>
<br>
you had installed a "flask" web server and a "bokeh" web server. You<br>
put the "flask" one behind nginx, so that clients would talk to nginx<br>
and to bokeh.<br>
<br>
And the clients were happy to talk http to nginx and http to bokeh.<br>
<br>
Then you enabled https on nginx, so that clients would talk https to<br>
nginx and http to bokeh.<br>
<br>
And the clients did not want to talk http to bokeh after talking https<br>
to nginx.<br>
<br>
So right now, you are trying to put the "bokeh" web server behind<br>
nginx too.<br>
<br>
There are various ips and ports and url prefixes that appear in various<br>
configuration files; it is worth making sure that you are very clear on<br>
what each one is for. That will make it possible to see what needs to<br>
be done to put bokeh behind nginx.<br>
<br>
<br>
> > >  3. in the Flask app, I changed the URL<br>
> > > to:url='<a href="https://138.197.132.46:5006/bokeh/" rel="noreferrer" target="_blank">https://138.197.132.<wbr>46:5006/bokeh/</a>'<br>
<br>
> > You can't mix 'https://' and :5006 port  in same url - this way the<br>
> > request<br>
> > goes to port 5006 but it expects to be also encrypted but if I understand<br>
> > correctly bokeh doesn't support SSL.<br>
<br>
> > What I forgot to add you need to change the 'url' (note the domain part)<br>
> > to:<br>
> ><br>
> > url='<a href="https://yourdomain/bokeh/" rel="noreferrer" target="_blank">https://yourdomain/bokeh/</a><wbr>'<br>
> ><br>
> > by looking at your error messages it seems that the 'url' is also directly<br>
> > used for client requests (probably placed in the html templated) - which<br>
> > means you can't use plain IP because then the browser most likely will just<br>
> > generate a SSL certificate and domain mismatch.<br>
<br>
> Thanks for answering again.<br>
><br>
> I followed your advise and change the Flask app script so that I have one<br>
> URL to pull the Bokeh session and another one to create the HTML script:<br>
><br>
> def company_abc():<br>
><br>
> url='<a href="http://127.0.0.1:5006/bokeh" rel="noreferrer" target="_blank">http://127.0.0.1:5006/<wbr>bokeh</a>'<br>
<br>
So: what is that url for?<br>
<br>
Is it a thing that the client web browser will try to access, or a thing<br>
that something internal to flask will try to access, or a thing that<br>
something internal to bokeh will try to access?<br>
<br>
When you can say what it is, then it may become clear what value it<br>
should have.<br>
<br>
> session=pull_session(url=url,<wbr>app_path="/company_abc")<br>
><br>
> url_https='<a href="https://www.example.com" rel="noreferrer" target="_blank">https://www.<wbr>example.com</a>'<br>
<br>
Same question. What is the purpose of that? Which of (browser, flask,<br>
bokeh) will try to use it?<br>
<br>
> > >                    proxy_pass <a href="http://127.0.0.1:5006" rel="noreferrer" target="_blank">http://127.0.0.1:5006</a>;  # you suggested<br>
> > 127.0.<br>
> > > *1*.1, but I figured that was a typo<br>
> ><br>
> > The proxy_pass address should be wherever your "bokeh" http server is<br>
> > actually listening.<br>
> ><br>
> > Which probably means that whatever you use up there...<br>
> ><br>
> > > command=/opt/envs/virtual/bin/<wbr>bokeh serve company_abc.py company_xyz.py<br>
> > > geomorphix.py --prefix=/bokeh/ --allow-websocket-origin=<a href="http://www.example.com" rel="noreferrer" target="_blank">www.<wbr>example.com</a><br>
> > > --allow-websocket-origin=<a href="http://example.com" rel="noreferrer" target="_blank">examp<wbr>le.com</a> --host=<a href="http://138.197.132.46:5006" rel="noreferrer" target="_blank">138.197.132.46:5006</a><br>
> > > --use-xheaders<br>
> ><br>
> > you should also use up there as --host.<br>
> ><br>
> > I suspect that making them both be 127.0.0.1 will be the easiest<br>
> > way of reverse-proxying things; but I also suspect that the<br>
> > "--allow-websocket-origin" part suggests that you may want to configure<br>
> > nginx to reverse proxy the web socket connection too. Notes are at<br>
> > <a href="http://nginx.org/en/docs/http/websocket.html" rel="noreferrer" target="_blank">http://nginx.org/en/docs/http/<wbr>websocket.html</a><br>
> ><br>
> > It will be helpful to have a very clear picture of what talks to what,<br>
> > when things are working normally; that should make it easier to be<br>
> > confident that the same links are in place with nginx in the mix.<br>
<br>
> As you suggested, I did the following:<br>
><br>
> 1. in '/etc/supervisor/conf.d/bokeh_<wbr>serve.conf' I changed the host to<br>
> <a href="http://127.0.0.1" rel="noreferrer" target="_blank">127.0.0.1</a>:<br>
><br>
> [program:bokeh_serve]<br>
><br>
> command=/opt/envs/virtual/bin/<wbr>bokeh serve company_abc.py --prefix=/bokeh/<br>
> --allow-websocket-origin=<a href="http://www.example.com" rel="noreferrer" target="_blank">www.<wbr>example.com</a> --allow-websocket-origin=<br>
> <a href="http://example.com" rel="noreferrer" target="_blank">example.com</a> --host=<a href="http://127.0.0.1:5006" rel="noreferrer" target="_blank">127.0.0.1:5006</a> <<a href="http://138.197.132.46:5006/" rel="noreferrer" target="_blank">http://138.197.132.46:5006/</a>><br>
>  --use-xheaders<br>
<br>
What is "--allow-websocket-origin" for? Is it causing any breakage here?<br>
<br>
(Can you temporarily run with all websocket origins allowed, until<br>
things work; and then add back the restrictions to confirm that things<br>
still work?)<br>
<br>
> 2. I configure nginx to reverse proxy the web socket connection by adding<br>
> the following lines to each location block in '/etc/nginx/sites-available/<br>
> default':<br>
<br>
That may or may not be needed in "each location". Maybe it is only needed<br>
in the "bokeh" location; the intended data flow diagram will show how<br>
things should be configured.<br>
<br>
> 3. In the Flask web app code I changed the URL of the route accordingly to<br>
> <a href="http://127.0.0.1" rel="noreferrer" target="_blank">127.0.0.1</a>:<br>
><br>
> @app.route("/company_abc/")<br>
><br>
> @login_required<br>
><br>
> @roles_accepted('company_abc', 'admin')<br>
><br>
> def geomorphix():<br>
><br>
>     url='<a href="http://127.0.0.1:5006/bokeh" rel="noreferrer" target="_blank">http://127.0.0.1:5006/<wbr>bokeh</a>'<br>
<br>
Same question as above: is that something that flask uses, or something<br>
that the web browser uses?<br>
<br>
Because the web browser will fail to access <a href="http://127.0.0.1:5006/" rel="noreferrer" target="_blank">http://127.0.0.1:5006/</a><br>
<br>
> When I enter the website with the Bokeh script in my browser, I get a<br>
> connection refused error:<br>
><br>
> GET <a href="http://127.0.0.1:5006/bokeh/example/autoload.js?bokeh-autoload-element=" rel="noreferrer" target="_blank">http://127.0.0.1:5006/bokeh/<wbr>example/autoload.js?bokeh-<wbr>autoload-element=</a>?<br>
> 9cf799610fb8&bokeh-session-id=<wbr>8tvMFfJwtVFccTctGHIRPPsT3h6IF6<wbr>nUFkJ8l6ZQALXl<br>
> net::ERR_CONNECTION_REFUSED<br>
<br>
That makes it look like the "url=" is something that the web browser uses.<br>
<br>
The web browser should only be accessing your <a href="https://nginx-server" rel="noreferrer" target="_blank">https://nginx-server</a><br>
service, so urls that the web browser will use should refer to that.<br>
<br>
Possibly "url='/bokeh'" will Just Work for you.<br>
<br>
You mentioned the bokeh documentation at<br>
<br>
<a href="http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#reverse-proxying-with-nginx-and-ssl" rel="noreferrer" target="_blank">http://bokeh.pydata.org/en/<wbr>latest/docs/user_guide/server.<wbr>html#reverse-proxying-with-<wbr>nginx-and-ssl</a><br>
<br>
and another link at<br>
<br>
<a href="http://stackoverflow.com/questions/38081389/bokeh-server-reverse-proxying-with-nginx-gives-404/38505205#38505205" rel="noreferrer" target="_blank">http://stackoverflow.com/<wbr>questions/38081389/bokeh-<wbr>server-reverse-proxying-with-<wbr>nginx-gives-404/38505205#<wbr>38505205</a><br>
<br>
in your first mail. Does your current nginx configuration resemble either<br>
of those?<br>
<br>
Good luck with it,<br>
<br>
        f<br>
--<br>
Francis Daly        <a href="mailto:francis@daoine.org">francis@daoine.org</a><br>
<br></blockquote></div></div></div>