1 from argparse
import ArgumentParser
2 from itertools
import chain
3 from secrets
import token_urlsafe
5 from subprocess
import run
7 from traceback
import print_exception
8 from typing
import List
, Optional
9 from urllib
.parse
import urlunsplit
11 from falcon
.asgi
import App
12 from falcon
.constants
import MEDIA_HTML
13 from uvicorn
import Config
, Server
15 from .staticresource
import StaticResource
20 def __init__(self
, secret
, browser
, hubapp
, *args
, **kwargs
):
21 kwargs
.setdefault("media_type", MEDIA_HTML
)
22 super().__init
__(*args
, **kwargs
)
23 self
.secret
= secret
or token_urlsafe(64)
24 self
.hub
= Hub(self
.secret
)
25 self
.sr
= StaticResource(self
.secret
, hubapp
)
26 self
.browser
= browser
27 self
.hub
.add_routes(self
)
28 self
.sr
.add_routes(self
)
29 self
.hub
.update_context_vars(self
.sr
.context_vars
)
30 self
.add_error_handler(Exception, self
.print_exception
)
32 async def print_exception(self
, req
, resp
, ex
, params
):
33 print_exception(*sys
.exc_info())
38 ap
.add_argument("--secret")
39 ap
.add_argument("--browser", default
="firefox")
40 ap
.add_argument("--hubapp", default
="first")
41 args
= ap
.parse_args()
42 return HubApp(args
.secret
, args
.browser
, args
.hubapp
)
45 class HubServer(Server
):
46 async def startup(self
, sockets
: Optional
[List
[socket
.socket
]] = None) -> None:
47 await super().startup(sockets
)
49 protocol_name
= "https" if config
.ssl
else "http"
50 host
= "0.0.0.0" if config
.host
is None else config
.host
52 # It's an IPv6 address.
53 host
= f
"[{host.rstrip(']').lstrip('[')}]"
59 chain
.from_iterable((server
.sockets
for server
in getattr(self
, "servers", ())))
63 if {"http": 80, "https": 443}
[protocol_name
] != port
:
64 host
= f
"{host}:{port}"
65 app
= config
.loaded_app
.app
66 print("master_uri", app
.sr
.master_uri
)
67 master_url
= urlunsplit((protocol_name
, host
, app
.sr
.master_uri
, "", ""))
68 print("secret:", app
.secret
)
70 print("master url", master_url
)
72 run([app
.browser
, master_url
])
77 Config("hub.app:get_app", factory
=True, port
=5000, log_level
="info")