【问题标题】:Bokeh server_document script loads from IP (HTTP) but not from domain (HTTPS)Bokeh server_document 脚本从 IP (HTTP) 加载,但不从域 (HTTPS) 加载
【发布时间】:2019-05-12 05:34:16
【问题描述】:

我在 Flask 和 Gunicorn 中嵌入了一个 Bokeh 应用程序(请参阅 flask_gunicorn_embed.py)。当我通过 Web 服务器的 IP 地址访问所有内容时,这可以正常工作,但当所有内容都通过 Nginx 代理时就不行了。它将从 Flask 加载所有内容,但不会从 Bokeh(autoload.js)加载。


示例:

我通过 Gunicorn 启动 Flask

gunicorn --workers 9 --bind 0.0.0.0:5000 --timeout 120 --log-file /some/directory/to/gunicorn/logs/gunicorn.log -m 0700 flask:app

我现在可以通过 http://xxx.xxx.xxx.xxx:5000 访问 Flask 中的所有内容。我已经改编了 flask_gunicorn_embed.py,最重要的部分是

script = server_document('http://xxx.xxx.xxx.xxx:%d/bkapp' % port, resources=None)
sockets, port = bind_sockets("0.0.0.0", 0)
bokeh_tornado = BokehTornado({'/bkapp': bkapp}, extra_websocket_origins=["xxx.xxx.xxx.xxx:5000"])

如果我现在访问使用此 Bokeh 服务器的页面,一切正常。它加载

http://xxx.xxx.xxx.xxx:XXXXX/bkapp/autoload.js?bokeh-autoload-element=1001&bokeh-app-path=/bkapp&bokeh-absolute-url=http://xxx.xxx.xxx.xxx:XXXXX/bkapp&resources=none

并显示图表,并为回调创建一个 Web 套接字。


这是没有 Nginx 作为反向代理。我不想使用 Web 服务器的 IP 地址,因为我需要使用 HTTPS,这需要一个域。

因此我有以下 Nginx 配置:

server {
    listen 80;
    server_name example.com;

    return 301 https://$server_name/;
}

server {
    listen 443;
    server_name example.com;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    client_max_body_size 50M;

    location / {
        include proxy_params;
        proxy_pass http://127.0.0.1:5000;
        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;
    }

    location /static {
        alias /some/directory/to/flask/static;
    }
}

我通过 Gunicorn 启动 Flask

gunicorn --workers 9 --bind 127.0.0.1:5000 --timeout 120 --log-file /some/directory/to/gunicorn/logs/gunicorn.log -m 0700 flask:app

我现在可以访问从 Flask 到 https://example.com 的所有内容。 flask_gunicorn_embed.py 现在看起来像

script = server_document('https://example.com:%d/bkapp' % port, resources=None)
sockets, port = bind_sockets("0.0.0.0", 0)
bokeh_tornado = BokehTornado({'/bkapp': bkapp}, extra_websocket_origins=["example.com"])

但是,通过 Bokeh 的server_document 生成的每个请求

https://example.com:XXXXX/bkapp/autoload.js?bokeh-autoload-element=1001&bokeh-app-path=/bkapp&bokeh-absolute-url=https://example.com:XXXXX/bkapp&resources=none

导致连接超时连接被拒绝,因此无法加载脚本。


我怎样才能让它连接并加载脚本?

它一定与 Nginx 有关,因为如果我通过 IP 地址请求文件,它仍然可以工作(由于bind_sockets("0.0.0.0", 0))。但我无法弄清楚是什么导致了这个问题。


编辑:

它使用 HTTPS 似乎是一个问题。我的 Nginx 配置与Bokeh documentation 中给出的配置相同。文档说使用--use_xheaders,这是不可能的,因为我没有使用bokeh serve

我有

conf = {'use_xheaders': True}
bokeh_tornado = BokehTornado({'/bkapp': bkapp}, extra_websocket_origins=["example.com"], **conf)
bokeh_http = HTTPServer(bokeh_tornado, xheaders=True)

但它仍然不会加载 HTTPS 页面的脚本。

http://example_no_https.com 将通过端口加载页面,https://example.com 不会。

【问题讨论】:

    标签: python nginx flask bokeh gunicorn


    【解决方案1】:

    use_xheaders 是 Bokeh Server 类的参数(将其传递给 Tornado HTTPServer),而不是 BokehTornado。如果您没有使用Server,因为您自己正在协调BokehTornadoHTTPServer,那么您将在HTTP 服务器上手动配置此选项,因为您没有Server 类为您执行此操作:

    http_server_kwargs.setdefault('xheaders', opts.use_xheaders)
    HTTPServer(..., **http_server_kwargs)
    

    【讨论】:

    • 感谢您的回答!我编辑了代码,但仍然无法连接/加载autoload.js 文件。它一定与端口有关,并且 Nginx 无法正确代理它,因为它不会完成 TLS 握手。
    • 或者别的什么,因为现在它只会抛出一个连接被拒绝的错误。
    猜你喜欢
    • 1970-01-01
    • 2017-01-07
    • 2020-07-04
    • 2017-12-14
    • 1970-01-01
    • 2018-04-05
    • 2012-02-18
    • 1970-01-01
    • 2012-02-10
    相关资源
    最近更新 更多