From 321fdf89b474a0ef01be637a52e26afc38b30998 Mon Sep 17 00:00:00 2001 From: Florian Bezannier Date: Wed, 16 Jun 2021 13:21:52 +0200 Subject: [PATCH] fix ingress --- web/app.py | 29 +++++++++++++++++++++-------- web/dash_custom.py | 28 ++++++++++++++++++++++++++++ web/views.py | 3 ++- 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 web/dash_custom.py diff --git a/web/app.py b/web/app.py index 140f10a..249f23e 100644 --- a/web/app.py +++ b/web/app.py @@ -1,12 +1,12 @@ import locale -import dash import dash_bootstrap_components as dbc from flask import Flask - from werkzeug import run_simple from werkzeug.middleware.proxy_fix import ProxyFix +from web.dash_custom import DashCustom + try: from werkzeug.middleware.dispatcher import DispatcherMiddleware except ImportError: @@ -22,13 +22,26 @@ dispatcher = None class MyProxyFix(ProxyFix): + def __init__(self, dashapp): + self.flask_app = dashapp.server + self.dash_app = dash_app + super().__init__(self.flask_app.wsgi_app, x_host=1, x_port=1, x_prefix=1) + def __call__(self, environ, start_response): - ingress_path = environ.get("HTTP_X_INGRESS_PATH") - if ingress_path: - environ["HTTP_X_FORWARDED_PREFIX"] = ingress_path + prefix = environ.get("HTTP_X_INGRESS_PATH") + if prefix: + environ["HTTP_X_FORWARDED_PREFIX"] = prefix + self.flask_app.config['APPLICATION_ROOT'] = environ['SCRIPT_NAME'] = prefix + prefix += "/" + self.dash_app.requests_pathname_external_prefix = prefix + self.dash_app.config.assets_external_path = prefix + else: + self.flask_app.config['APPLICATION_ROOT'] = "/" + self.dash_app.requests_pathname_external_prefix = "/" return super().__call__(environ, start_response) + def start_app(*args, **kwargs): run(config_flask(*args, **kwargs)) @@ -47,7 +60,6 @@ def config_flask(title, base_path, debug: bool, host, port, reloader=False, # p logger.warning("Can't get language") if unminified: locale_url = ["assets/plotly-with-meta.js"] - app.wsgi_app = MyProxyFix(app.wsgi_app, x_prefix=1) app.config["DEBUG"] = debug if base_path == "/": application = DispatcherMiddleware(app) @@ -55,10 +67,11 @@ def config_flask(title, base_path, debug: bool, host, port, reloader=False, # p else: application = DispatcherMiddleware(Flask('dummy_app'), {base_path: app}) requests_pathname_prefix = base_path + "/" - dash_app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], external_scripts=locale_url, title=title, + dash_app = DashCustom(external_stylesheets=[dbc.themes.BOOTSTRAP], external_scripts=locale_url, title=title, server=app, requests_pathname_prefix=requests_pathname_prefix, - suppress_callback_exceptions=True) + suppress_callback_exceptions=True, serve_locally=False) dash_app.enable_dev_tools(reloader) + app.wsgi_app = MyProxyFix(dash_app) # keep this line importlib.import_module(view) if reload_view: diff --git a/web/dash_custom.py b/web/dash_custom.py new file mode 100644 index 0000000..5f9d143 --- /dev/null +++ b/web/dash_custom.py @@ -0,0 +1,28 @@ +from dash import Dash + +class DashCustom(Dash): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.requests_pathname_external_prefix = self.config.requests_pathname_prefix + + def _config(self): + # pieces of config needed by the front end + config = { + "url_base_pathname": self.config.url_base_pathname, + "requests_pathname_prefix": self.requests_pathname_external_prefix, + "ui": self._dev_tools.ui, + "props_check": self._dev_tools.props_check, + "show_undo_redo": self.config.show_undo_redo, + "suppress_callback_exceptions": self.config.suppress_callback_exceptions, + "update_title": self.config.update_title, + } + if self._dev_tools.hot_reload: + config["hot_reload"] = { + # convert from seconds to msec as used by js `setInterval` + "interval": int(self._dev_tools.hot_reload_interval * 1000), + "max_retry": self._dev_tools.hot_reload_max_retry, + } + if self.validation_layout and not self.config.suppress_callback_exceptions: + config["validation_layout"] = self.validation_layout + + return config diff --git a/web/views.py b/web/views.py index fcd2143..82d09fd 100644 --- a/web/views.py +++ b/web/views.py @@ -42,12 +42,13 @@ CONFIG = Config() @dash_app.callback(Output('page-content', 'children'), [Input('url', 'pathname')]) def display_page(pathname): + pathname = pathname[len(dash_app.requests_pathname_external_prefix)-1:] if pathname == "/config": return config_layout if pathname == "/log": return log_layout() if not CONFIG.is_good: - return dcc.Location(pathname="/config", id="config_redirect") + return dcc.Location(pathname=dash_app.requests_pathname_external_prefix + "config", id="config_redirect") if pathname == "/config_otp": return config_otp_layout return serve_layout()