3 from argparse
import ArgumentParser
4 from itertools
import chain
5 from pathlib
import Path
6 from secrets
import token_urlsafe
7 from subprocess
import run
8 from traceback
import print_exception
9 from urllib
.parse
import urlunsplit
11 from falcon
.asgi
import App
as FalconApp
12 from falcon
.constants
import MEDIA_HTML
13 from jinja2
import Environment
, FileSystemLoader
, select_autoescape
14 from uvicorn
import Config
, Server
16 from .hubapp
import HubApp
, RootApp
20 def __init__(self
, secret
, **kwargs
):
21 kwargs
.setdefault("media_type", MEDIA_HTML
)
22 super().__init
__(**kwargs
)
23 self
.base_dir
= Path(__file__
).parents
[1] / "webroot"
24 self
.env
= Environment(
25 loader
=FileSystemLoader(self
.base_dir
),
26 autoescape
=select_autoescape
,
27 extensions
=["hub.utils.StaticTag"],
29 self
.secret
= secret
or token_urlsafe(64)
31 RootApp(self
, self
.base_dir
)
32 for base_dir
in self
.base_dir
.iterdir():
33 if not base_dir
.is_dir() or HubApp
.is_ignored_filename(base_dir
):
35 HubApp(self
, base_dir
)
36 self
.add_error_handler(Exception, self
.print_exception
)
38 def get_hubapp_by_name(self
, name
):
39 return self
.hubapps
[name
]
41 async def print_exception(self
, req
, resp
, ex
, params
):
42 print_exception(*sys
.exc_info())
45 class HubServer(Server
):
46 def __init__(self
, *args
, browser
, **kwargs
):
47 self
.browser
= browser
48 super().__init
__(*args
, **kwargs
)
50 async def startup(self
, sockets
: list[socket
.socket
] |
None = None) -> None:
51 await super().startup(sockets
)
53 protocol_name
= "https" if config
.ssl
else "http"
54 host
= "0.0.0.0" if config
.host
is None else config
.host
56 # It's an IPv6 address.
57 host
= f
"[{host.rstrip(']').lstrip('[')}]"
64 (server
.sockets
for server
in getattr(self
, "servers", ()))
69 if {"http": 80, "https": 443}
[protocol_name
] != port
:
70 host
= f
"{host}:{port}"
71 app
= config
.loaded_app
.app
72 print("Secret:", app
.secret
)
73 for key
, value
in app
.hubapps
["root"].files_per_uris
.items():
74 if Path(value
.path
.name
).stem
== "index.html":
75 url
= urlunsplit((protocol_name
, host
, key
, "", ""))
78 run([self
.browser
, url
])
87 ap
.add_argument("--secret")
88 ap
.add_argument("--browser", default
="firefox")
89 args
= ap
.parse_args()
90 app
= App(args
.secret
)
91 config
= Config("hub.app:app", port
=5000, log_level
="info")
92 config
.setup_event_loop()
93 hs
= HubServer(config
, browser
=args
.browser
)