diff options
Diffstat (limited to 'src/hydrilla/proxy/web_ui/root.py')
-rw-r--r-- | src/hydrilla/proxy/web_ui/root.py | 69 |
1 files changed, 55 insertions, 14 deletions
diff --git a/src/hydrilla/proxy/web_ui/root.py b/src/hydrilla/proxy/web_ui/root.py index 18ea18e..57dc958 100644 --- a/src/hydrilla/proxy/web_ui/root.py +++ b/src/hydrilla/proxy/web_ui/root.py @@ -29,6 +29,7 @@ ..... """ +import dataclasses as dc import typing as t from threading import Lock @@ -71,10 +72,21 @@ def get_settings() -> st.HaketiloGlobalSettings: return _app.get_haketilo_state().get_settings() +@dc.dataclass(init=False) class WebUIAppImpl(_app.WebUIApp): + # Flask app is not thread-safe and has to be accompanied by an ugly lock. + # This can cause slow requests to block other requests, so we might need a + # better workaround at some later point. + _haketilo_app_lock: Lock + + _haketilo_blueprints: t.ClassVar[t.Sequence[flask.Blueprint]] + _haketilo_ui_domain: t.ClassVar[_app.UIDomain] + def __init__(self): super().__init__(__name__) + self._haketilo_app_lock = Lock() + self.jinja_options = { **self.jinja_options, 'loader': jinja2.PackageLoader(__package__), @@ -99,19 +111,13 @@ class WebUIAppImpl(_app.WebUIApp): self.before_request(authenticate_by_referrer) - for blueprint in [ - rules.bp, repos.bp, items.bp, items_import.bp, prompts.bp - ]: - self.register_blueprint(blueprint) + for bp in self._haketilo_blueprints: + self.register_blueprint(bp) -# Flask app is not thread-safe and has to be accompanied by an ugly lock. This -# can cause slow requests to block other requests, so we might need a better -# workaround at some later point. -app = WebUIAppImpl() -app_lock = Lock() +home_bp = flask.Blueprint('home', __package__) -@app.route('/', methods=['GET']) +@home_bp.route('/', methods=['GET']) def home(errors: t.Mapping[str, bool] = {}) -> werkzeug.Response: state = _app.get_haketilo_state() @@ -122,7 +128,7 @@ def home(errors: t.Mapping[str, bool] = {}) -> werkzeug.Response: ) return flask.make_response(html, 200) -@app.route('/', methods=['POST']) +@home_bp.route('/', methods=['POST']) def home_post() -> werkzeug.Response: action = flask.request.form['action'] @@ -149,22 +155,57 @@ def home_post() -> werkzeug.Response: return flask.redirect(flask.url_for('.home'), 303) +blueprints_main = \ + (rules.bp, repos.bp, items.bp, items_import.bp, prompts.bp, home_bp) + +@dc.dataclass(init=False) +class AppMain(WebUIAppImpl): + _haketilo_blueprints = blueprints_main + _haketilo_ui_domain = _app.UIDomain.MAIN + + +landing_bp = flask.Blueprint('landing_page', __package__) + +@landing_bp.route('/', methods=['GET']) +def landing(errors: t.Mapping[str, bool] = {}) -> werkzeug.Response: + state = _app.get_haketilo_state() + + html = flask.render_template( + 'landing.html.jinja', + listen_host = state.listen_host, + listen_port = state.listen_port + ) + return flask.make_response(html, 200) + +@dc.dataclass(init=False) +class AppLandingPage(WebUIAppImpl): + _haketilo_blueprints = (landing_bp,) + _haketilo_ui_domain = _app.UIDomain.LANDING_PAGE + + +apps_seq = [AppMain(), AppLandingPage()] +apps = dict((app._haketilo_ui_domain, app) for app in apps_seq) + + def process_request( request_info: http_messages.RequestInfo, - state: st.HaketiloState + state: st.HaketiloState, + ui_domain: _app.UIDomain = _app.UIDomain.MAIN ) -> http_messages.ProducedResponse: path = '/'.join(('', *request_info.url.path_segments)) if (request_info.url.has_trailing_slash): path += '/' - with app_lock: + app = apps[ui_domain] + + with app._haketilo_app_lock: app._haketilo_state = state app.jinja_env.install_gettext_translations(make_translation()) flask_response = app.test_client().open( path = path, - base_url = f'{request_info.url.scheme}://hkt.mitm.it', + base_url = request_info.url.url_without_path, method = request_info.method, query_string = request_info.url.query, headers = [*request_info.headers.items()], |