X-Git-Url: https://git.mar77i.info/?a=blobdiff_plain;f=hub%2Fapp.py;h=959024f2c2a41bd2bd3e223e6b58bc12a0c444db;hb=6128e895bc2a5da5fe645cc9a7ad74ac75af4f6b;hp=24212d0972581d1e6e7bef054074c80f8b229c6b;hpb=d23acd0d6d03d822e4505c64f71587f55e8dc2b6;p=hublib diff --git a/hub/app.py b/hub/app.py index 24212d0..959024f 100644 --- a/hub/app.py +++ b/hub/app.py @@ -1,16 +1,96 @@ +import socket +import sys from argparse import ArgumentParser +from itertools import chain +from pathlib import Path +from secrets import token_urlsafe +from subprocess import run +from traceback import print_exception +from urllib.parse import urlunsplit -from falcon.asgi import App +from falcon.asgi import App as FalconApp from falcon.constants import MEDIA_HTML +from jinja2 import Environment, FileSystemLoader, select_autoescape +from uvicorn import Config, Server -from .cryptresource import CryptResource +from .hubapp import HubApp, RootApp -def get_app(): - app = App(media_type=MEDIA_HTML) +class App(FalconApp): + def __init__(self, secret, **kwargs): + kwargs.setdefault("media_type", MEDIA_HTML) + super().__init__(**kwargs) + self.base_dir = Path(__file__).parents[1] / "webroot" + self.env = Environment( + loader=FileSystemLoader(self.base_dir), + autoescape=select_autoescape, + extensions=["hub.utils.StaticTag"], + ) + self.secret = secret or token_urlsafe(64) + self.hubapps = {} + RootApp(self, self.base_dir) + for base_dir in self.base_dir.iterdir(): + if not base_dir.is_dir() or HubApp.is_ignored_filename(base_dir): + continue + HubApp(self, base_dir) + self.add_error_handler(Exception, self.print_exception) + + def get_hubapp_by_name(self, name): + if name == "root": + name = "" + return self.hubapps[name] + + async def print_exception(self, req, resp, ex, params): + print_exception(*sys.exc_info()) + + +class HubServer(Server): + def __init__(self, *args, browser, **kwargs): + self.browser = browser + super().__init__(*args, **kwargs) + + async def startup(self, sockets: list[socket.socket] | None = None) -> None: + await super().startup(sockets) + config = self.config + protocol_name = "https" if config.ssl else "http" + host = "0.0.0.0" if config.host is None else config.host + if ":" in host: + # It's an IPv6 address. + host = f"[{host.rstrip(']').lstrip('[')}]" + + port = config.port + if port == 0: + try: + port = next( + chain.from_iterable( + (server.sockets for server in getattr(self, "servers", ())) + ) + ).getsockname()[1] + except StopIteration: + pass + if {"http": 80, "https": 443}[protocol_name] != port: + host = f"{host}:{port}" + app = config.loaded_app.app + print("Secret:", app.secret) + for key, value in app.root_app.files_per_uris.items(): + if Path(value.path.name).stem == "index.html": + url = urlunsplit((protocol_name, host, key, "", "")) + print("URL:", url) + if self.browser: + run([self.browser, url]) + + +app: App + + +async def main(): + global app ap = ArgumentParser() ap.add_argument("--secret") + ap.add_argument("--browser", default="firefox") args = ap.parse_args() - cr = CryptResource(args.secret) - cr.register_on(app) - return app + app = App(args.secret) + config = Config("hub.app:app", port=5000, log_level="info") + config.setup_event_loop() + hs = HubServer(config, browser=args.browser) + await hs.serve()