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
, self
.hub
.master_ws_uri
)
26 self
.browser
= browser
27 self
.hub
.add_routes(self
)
28 self
.sr
.add_routes(self
)
29 self
.add_error_handler(Exception, self
.print_exception
)
31 async def print_exception(self
, req
, resp
, ex
, params
):
32 print_exception(*sys
.exc_info())
37 ap
.add_argument("--secret")
38 ap
.add_argument("--browser", default
="firefox")
39 ap
.add_argument("--hubapp", default
="first")
40 args
= ap
.parse_args()
41 return HubApp(args
.secret
, args
.browser
, args
.hubapp
)
44 class HubServer(Server
):
45 async def startup(self
, sockets
: Optional
[List
[socket
.socket
]] = None) -> None:
46 await super().startup(sockets
)
48 protocol_name
= "https" if config
.ssl
else "http"
49 host
= "0.0.0.0" if config
.host
is None else config
.host
51 # It's an IPv6 address.
52 host
= f
"[{host.rstrip(']').lstrip('[')}]"
58 chain
.from_iterable((server
.sockets
for server
in getattr(self
, "servers", ())))
62 if {"http": 80, "https": 443}
[protocol_name
] != port
:
63 host
= f
"{host}:{port}"
64 app
= config
.loaded_app
.app
65 print("master_uri", app
.sr
.master_uri
)
66 master_url
= urlunsplit((protocol_name
, host
, app
.sr
.master_uri
, "", ""))
67 print("secret:", app
.secret
)
69 print("master url", master_url
)
71 run([app
.browser
, master_url
])
76 Config("hub.app:get_app", factory
=True, port
=5000, log_level
="info")