aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-08-12 14:33:15 +0200
committerWojtek Kosior <koszko@koszko.org>2022-08-12 14:33:15 +0200
commit2c98d04e4d4a344dc04a481b039a235678f7848e (patch)
tree292b858fa07613c3c455961f17adf33e64db92e8
parent3d025bfb796d3028282bc806d557b8289a42062b (diff)
downloadhaketilo-hydrilla-2c98d04e4d4a344dc04a481b039a235678f7848e.tar.gz
haketilo-hydrilla-2c98d04e4d4a344dc04a481b039a235678f7848e.zip
make Haketilo proxy web UI in terms of a Flask app
-rw-r--r--src/hydrilla/proxy/policies/web_ui.py2
-rw-r--r--src/hydrilla/proxy/web_ui/__init__.py2
-rw-r--r--src/hydrilla/proxy/web_ui/packages.py44
-rw-r--r--src/hydrilla/proxy/web_ui/repos.py23
-rw-r--r--src/hydrilla/proxy/web_ui/root.py71
-rw-r--r--src/hydrilla/proxy/web_ui/templates/base.html.jinja32
-rw-r--r--src/hydrilla/proxy/web_ui/templates/packages__load_from_disk.html.jinja26
-rw-r--r--src/hydrilla/proxy/web_ui/templates/repos.html.jinja26
-rw-r--r--src/hydrilla/proxy/web_ui/templates/root.html.jinja26
-rw-r--r--src/hydrilla/url_patterns.py4
10 files changed, 224 insertions, 32 deletions
diff --git a/src/hydrilla/proxy/policies/web_ui.py b/src/hydrilla/proxy/policies/web_ui.py
index 5040278..6fbb4aa 100644
--- a/src/hydrilla/proxy/policies/web_ui.py
+++ b/src/hydrilla/proxy/policies/web_ui.py
@@ -52,7 +52,7 @@ class WebUIPolicy(base.Policy):
def consume_request(self, request_info: http_messages.RequestInfo) \
-> http_messages.ProducedResponse:
- return web_ui.respond(request_info, self.haketilo_state)
+ return web_ui.process_request(request_info, self.haketilo_state)
@dc.dataclass(frozen=True, unsafe_hash=True)
diff --git a/src/hydrilla/proxy/web_ui/__init__.py b/src/hydrilla/proxy/web_ui/__init__.py
index ba461b1..a5dddab 100644
--- a/src/hydrilla/proxy/web_ui/__init__.py
+++ b/src/hydrilla/proxy/web_ui/__init__.py
@@ -4,4 +4,4 @@
#
# Available under the terms of Creative Commons Zero v1.0 Universal.
-from .root import respond
+from .root import process_request
diff --git a/src/hydrilla/proxy/web_ui/packages.py b/src/hydrilla/proxy/web_ui/packages.py
new file mode 100644
index 0000000..7d67b63
--- /dev/null
+++ b/src/hydrilla/proxy/web_ui/packages.py
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# Proxy web UI packages loading.
+#
+# This file is part of Hydrilla&Haketilo.
+#
+# Copyright (C) 2022 Wojtek Kosior
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#
+# I, Wojtek Kosior, thereby promise not to sue for violation of this
+# file's license. Although I request that you do not make use this code
+# in a proprietary program, I am not going to enforce this in court.
+
+"""
+.....
+"""
+
+# Enable using with Python 3.7.
+from __future__ import annotations
+
+import typing as t
+
+import flask
+
+
+bp = flask.Blueprint('load_packages', __package__)
+
+@bp.route('/packages/load_from_disk')
+def load_from_disk() -> flask.Response:
+ html = flask.render_template('packages__load_from_disk.html.jinja')
+ return flask.make_response(html, 200)
diff --git a/src/hydrilla/proxy/web_ui/repos.py b/src/hydrilla/proxy/web_ui/repos.py
index d20791c..0f55b2a 100644
--- a/src/hydrilla/proxy/web_ui/repos.py
+++ b/src/hydrilla/proxy/web_ui/repos.py
@@ -33,17 +33,12 @@ from __future__ import annotations
import typing as t
-from ...translations import smart_gettext as _
-from .. import state as st
-from .. import http_messages
-
-def respond(
- request: http_messages.RequestInfo,
- rest_of_path: t.Sequence[str],
- state: st.HaketiloState
-) -> http_messages.ProducedResponse:
- return http_messages.ProducedResponse(
- 404,
- [(b'Content-Type', b'text/plain; charset=utf-8')],
- _('api.repos_not_implemented').encode()
- )
+import flask
+
+
+bp = flask.Blueprint('repos', __package__)
+
+@bp.route('/repos')
+def repos() -> flask.Response:
+ html = flask.render_template('repos.html.jinja')
+ return flask.make_response(html, 200)
diff --git a/src/hydrilla/proxy/web_ui/root.py b/src/hydrilla/proxy/web_ui/root.py
index dbb86c1..194251e 100644
--- a/src/hydrilla/proxy/web_ui/root.py
+++ b/src/hydrilla/proxy/web_ui/root.py
@@ -32,35 +32,74 @@
from __future__ import annotations
import typing as t
+from threading import Lock
+
+import jinja2
+import flask
from ...translations import smart_gettext as _
from .. import state as st
from .. import http_messages
from . import repos
+from . import packages
+
+
+class WebUIApp(flask.Flask):
+ def __init__(self):
+ super().__init__(__name__)
+
+ self.jinja_options = {
+ **self.jinja_options,
+ 'loader': jinja2.PackageLoader(__package__),
+ 'autoescape': jinja2.select_autoescape()
+ }
+ for blueprint in [repos.bp, packages.bp]:
+ self.register_blueprint(blueprint)
-HandlerType = t.Callable[
- [http_messages.RequestInfo, t.Sequence[str], st.HaketiloState],
- http_messages.ProducedResponse
-]
+ _haketilo_state: st.HaketiloState
-request_handlers: t.Mapping[str, HandlerType] = {
- 'repos': repos.respond
-}
+# 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 = WebUIApp()
+app_lock = Lock()
-def respond(
+
+@app.route('/')
+def respond():
+ return flask.render_template('root.html.jinja')
+
+
+def process_request(
request_info: http_messages.RequestInfo,
state: st.HaketiloState
) -> http_messages.ProducedResponse:
- if request_info.url.path_segments == ():
- raise NotImplementedError()
+ path = '/'.join(('', *request_info.url.path_segments))
+ if (request_info.url.has_trailing_slash):
+ path += '/'
+
+ with app_lock:
+ app._haketilo_state = state
- resource, *rest_of_path = request_info.url.path_segments
+ flask_response = app.test_client().open(
+ path = path,
+ base_url = 'https://hkt.mitm.it',
+ method = request_info.method,
+ query_string = request_info.url.query,
+ headers = [*request_info.headers.items()],
+ data = request_info.body
+ )
- try:
- handler = request_handlers[resource]
- except KeyError:
- raise NotImplementedError()
+ headers_bytes = [
+ (key.encode(), val.encode())
+ for key, val
+ in flask_response.headers
+ ]
- return handler(request_info, rest_of_path, state)
+ return http_messages.ProducedResponse(
+ status_code = flask_response.status_code,
+ headers = headers_bytes,
+ body = flask_response.data
+ )
diff --git a/src/hydrilla/proxy/web_ui/templates/base.html.jinja b/src/hydrilla/proxy/web_ui/templates/base.html.jinja
new file mode 100644
index 0000000..c6f0dcf
--- /dev/null
+++ b/src/hydrilla/proxy/web_ui/templates/base.html.jinja
@@ -0,0 +1,32 @@
+{#
+SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0
+
+
+Proxy web UI base page template.
+
+This file is part of Hydrilla&Haketilo.
+
+Copyright (C) 2022 Wojtek Kosior
+
+Dual licensed under
+* GNU General Public License v3.0 or later and
+* Creative Commons Attribution Share Alike 4.0 International.
+
+You can choose to use either of these licenses or both.
+
+
+I, Wojtek Kosior, thereby promise not to sue for violation of this
+file's licenses. Although I request that you do not make use this code
+in a proprietary work, I am not going to enforce this in court.
+#}
+<!DOCTYPE html>
+<html>
+ <head>
+ {% block head %}
+ <title>{% block title required %}{% endblock %} - Haketilo proxy</title>
+ {% endblock %}
+ </head>
+ <body>
+ <div id="main">{% block main required %}{% endblock %}</div>
+ </body>
+</html>
diff --git a/src/hydrilla/proxy/web_ui/templates/packages__load_from_disk.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages__load_from_disk.html.jinja
new file mode 100644
index 0000000..07ed3b3
--- /dev/null
+++ b/src/hydrilla/proxy/web_ui/templates/packages__load_from_disk.html.jinja
@@ -0,0 +1,26 @@
+{#
+Spdx-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0
+
+
+Proxy web UI package loading page.
+
+This file is part of Hydrilla&Haketilo.
+
+Copyright (C) 2022 Wojtek Kosior
+
+Dual licensed under
+* GNU General Public License v3.0 or later and
+* Creative Commons Attribution Share Alike 4.0 International.
+
+You can choose to use either of these licenses or both.
+
+
+I, Wojtek Kosior, thereby promise not to sue for violation of this
+file's licenses. Although I request that you do not make use this code
+in a proprietary work, I am not going to enforce this in court.
+#}
+{% extends "base.html.jinja" %}
+{% block title %}Load package{% endblock %}
+{% block main %}
+ Not implemented yet :(
+{% endblock %}
diff --git a/src/hydrilla/proxy/web_ui/templates/repos.html.jinja b/src/hydrilla/proxy/web_ui/templates/repos.html.jinja
new file mode 100644
index 0000000..59eb1bd
--- /dev/null
+++ b/src/hydrilla/proxy/web_ui/templates/repos.html.jinja
@@ -0,0 +1,26 @@
+{#
+SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0
+
+
+Proxy web UI repos list page.
+
+This file is part of Hydrilla&Haketilo.
+
+Copyright (C) 2022 Wojtek Kosior
+
+Dual licensed under
+* GNU General Public License v3.0 or later and
+* Creative Commons Attribution Share Alike 4.0 International.
+
+You can choose to use either of these licenses or both.
+
+
+I, Wojtek Kosior, thereby promise not to sue for violation of this
+file's licenses. Although I request that you do not make use this code
+in a proprietary work, I am not going to enforce this in court.
+#}
+{% extends "base.html.jinja" %}
+{% block title %}Repositories{% endblock %}
+{% block main %}
+ Not implemented yet :(
+{% endblock %}
diff --git a/src/hydrilla/proxy/web_ui/templates/root.html.jinja b/src/hydrilla/proxy/web_ui/templates/root.html.jinja
new file mode 100644
index 0000000..f1e3500
--- /dev/null
+++ b/src/hydrilla/proxy/web_ui/templates/root.html.jinja
@@ -0,0 +1,26 @@
+{#
+SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0
+
+
+Proxy web UI root page.
+
+This file is part of Hydrilla&Haketilo.
+
+Copyright (C) 2022 Wojtek Kosior
+
+Dual licensed under
+* GNU General Public License v3.0 or later and
+* Creative Commons Attribution Share Alike 4.0 International.
+
+You can choose to use either of these licenses or both.
+
+
+I, Wojtek Kosior, thereby promise not to sue for violation of this
+file's licenses. Although I request that you do not make use this code
+in a proprietary work, I am not going to enforce this in court.
+#}
+{% extends "base.html.jinja" %}
+{% block title %}Home{% endblock %}
+{% block main %}
+ <a href="/packages/load_from_disk">load packages from disk</a>
+{% endblock %}
diff --git a/src/hydrilla/url_patterns.py b/src/hydrilla/url_patterns.py
index 0a242e3..278827a 100644
--- a/src/hydrilla/url_patterns.py
+++ b/src/hydrilla/url_patterns.py
@@ -55,6 +55,7 @@ class ParsedUrl:
scheme: str = dc.field(hash=False, compare=False)
domain_labels: tuple[str, ...] = dc.field(hash=False, compare=False)
path_segments: tuple[str, ...] = dc.field(hash=False, compare=False)
+ query: str = dc.field(hash=False, compare=False)
has_trailing_slash: bool = dc.field(hash=False, compare=False)
port: int = dc.field(hash=False, compare=False)
@@ -189,12 +190,15 @@ def _parse_pattern_or_url(url: str, orig_url: str, is_pattern: bool = False) \
msg = _('err.url_pattern_{}.has_frag').format(orig_url)
raise HaketiloException(msg)
+ query = parse_result.query
+
return ParsedUrl(
orig_url = orig_url,
scheme = scheme,
port = port,
domain_labels = domain_labels,
path_segments = path_segments,
+ query = query,
has_trailing_slash = has_trailing_slash
)