# SPDX-License-Identifier: GPL-3.0-or-later # Proxy web UI root. # # 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 . # # # 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 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) _haketilo_state: st.HaketiloState # 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() @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: path = '/'.join(('', *request_info.url.path_segments)) if (request_info.url.has_trailing_slash): path += '/' with app_lock: app._haketilo_state = state 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 ) headers_bytes = [ (key.encode(), val.encode()) for key, val in flask_response.headers ] return http_messages.ProducedResponse( status_code = flask_response.status_code, headers = headers_bytes, body = flask_response.data )