Skip to content

Commit f67274f

Browse files
committed
Refactored the server for readability
1 parent be0025b commit f67274f

3 files changed

Lines changed: 97 additions & 83 deletions

File tree

‎bluesky_httpserver/server.py‎

Lines changed: 7 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import argparse
21
import logging
32
import os
43
import pprint
@@ -9,8 +8,8 @@
98

109
from .app import build_app
1110
from .config import construct_build_app_kwargs, parse_configs
12-
from .settings import get_settings
13-
from .utils import get_authenticators
11+
from .server.server_args import server_arg_parser
12+
from .server.server_utils import print_admin_api_key_if_generated
1413

1514
logger = logging.getLogger(__name__)
1615

@@ -24,78 +23,28 @@ def start_server():
2423
logging.basicConfig(level=logging.WARNING)
2524
logging.getLogger("bluesky_httpserver").setLevel("INFO")
2625

27-
def formatter(prog):
28-
# Set maximum width such that printed help mostly fits in the RTD theme code block (documentation).
29-
return argparse.RawDescriptionHelpFormatter(prog, max_help_position=20, width=90)
30-
31-
parser = argparse.ArgumentParser(
32-
description="Start Bluesky HTTP Server.\n" f"bluesky-httpserver version {qserver_version}.\n",
33-
formatter_class=formatter,
34-
)
35-
36-
parser.add_argument(
37-
"--host",
38-
dest="http_server_host",
39-
action="store",
40-
default=None,
41-
help="HTTP server host name, e.g. '127.0.0.1' or 'localhost' " f"(default: {default_http_server_host!r}).",
42-
)
43-
44-
parser.add_argument(
45-
"--port",
46-
dest="http_server_port",
47-
action="store",
48-
default=None,
49-
help="HTTP server port, e.g. '127.0.0.1' or 'localhost' " f"(default: {default_http_server_port!r}).",
50-
)
51-
52-
parser.add_argument(
53-
"--public",
54-
dest="public",
55-
action="store_true",
56-
default=False,
57-
help="Explicitly allows public access to the server and disables authorization/authentication.",
58-
)
59-
60-
parser.add_argument(
61-
"--config_path",
62-
dest="config_path",
63-
action="store",
64-
default=None,
65-
help="Path to configuration file or directory with configuration files. The path overrides "
66-
"the path defined in QSERVER_HTTP_SERVER_CONFIG environment variable. If the parameter and "
67-
"the environemnt variable is not specified, then no configuration file is loaded.",
68-
)
69-
70-
args = parser.parse_args()
71-
72-
public = args.public
73-
config_path = args.config_path
74-
75-
http_server_host = args.http_server_host
76-
http_server_port = args.http_server_port
77-
http_server_port = int(http_server_port) if http_server_port else http_server_port
26+
args = server_arg_parser()
7827

7928
logger.info("Preparing to start Bluesky HTTP Server ...")
8029

81-
config_path = config_path or os.getenv("QSERVER_HTTP_SERVER_CONFIG", None)
30+
config_path = args.config_path or os.getenv("QSERVER_HTTP_SERVER_CONFIG", None)
8231
try:
8332
parsed_config = parse_configs(config_path) if config_path else {}
8433
except Exception as ex:
8534
logger.error(ex)
8635
raise
8736

8837
# Let --public flag override settings in config.
89-
if public:
38+
if args.public:
9039
if "authentication" not in parsed_config:
9140
parsed_config["authentication"] = {}
9241
parsed_config["authentication"]["allow_anonymous_access"] = True
9342

9443
# Extract config for uvicorn.
9544
uvicorn_kwargs = parsed_config.pop("uvicorn", {})
9645
# 'host' and 'port' from CLI parameters overrides the parameters from config.
97-
uvicorn_kwargs["host"] = http_server_host or uvicorn_kwargs.get("host", default_http_server_host)
98-
uvicorn_kwargs["port"] = http_server_port or uvicorn_kwargs.get("port", default_http_server_port)
46+
uvicorn_kwargs["host"] = args.http_server_host or uvicorn_kwargs.get("host", default_http_server_host)
47+
uvicorn_kwargs["port"] = args.http_server_port or uvicorn_kwargs.get("port", default_http_server_port)
9948

10049
# This config was already validated when it was parsed. Do not re-validate.
10150
kwargs = construct_build_app_kwargs(parsed_config, source_filepath=config_path)
@@ -113,31 +62,6 @@ def formatter(prog):
11362

11463
uvicorn.run(web_app, **uvicorn_kwargs)
11564

116-
117-
def print_admin_api_key_if_generated(web_app, host, port):
118-
# host = host or "127.0.0.1"
119-
# port = port or 8000
120-
settings = web_app.dependency_overrides.get(get_settings, get_settings)()
121-
122-
logger.info("APP settings: %s", pprint.pformat(dict(settings)))
123-
authenticators = web_app.dependency_overrides.get(get_authenticators, get_authenticators)()
124-
if settings.allow_anonymous_access:
125-
print(
126-
"The server is running in 'public' mode, permitting open, anonymous access\n"
127-
"for reading. Any data that is not specifically controlled with an access\n"
128-
"policy will be visible to anyone who can connect to this server.\n",
129-
file=sys.stderr,
130-
)
131-
if (not authenticators) and settings.single_user_api_key_generated:
132-
print(
133-
"Navigate a web browser to:\n\n"
134-
f"http://{host}:{port}?api_key={settings.single_user_api_key}\n\n"
135-
"or connect an HTTP client to:\n\n"
136-
f"http://{host}:{port}/api?api_key={settings.single_user_api_key}\n",
137-
file=sys.stderr,
138-
)
139-
140-
14165
def app_factory():
14266
"""
14367
Return an ASGI app instance.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import argparse
2+
from typing import NamedTuple
3+
4+
def formatter(prog):
5+
# Set maximum width such that printed help mostly fits in the RTD theme code block (documentation).
6+
return argparse.RawDescriptionHelpFormatter(prog, max_help_position=20, width=90)
7+
8+
class ServerArgs(NamedTuple):
9+
public: str
10+
config_path: str
11+
http_server_port: int
12+
http_server_host: str
13+
14+
def sanitize_parsed_args(args):
15+
server_args = ServerArgs()
16+
server_args.public = args.public
17+
server_args.config_path = args.config_path
18+
19+
server_args.http_server_host = args.http_server_host
20+
http_server_port = args.http_server_port
21+
server_args.http_server_port = int(http_server_port) if http_server_port else http_server_port
22+
23+
return server_args
24+
25+
def server_arg_parser():
26+
parser = argparse.ArgumentParser(
27+
description="Start Bluesky HTTP Server.\n" f"bluesky-httpserver version {qserver_version}.\n",
28+
formatter_class=formatter,
29+
)
30+
31+
parser.add_argument(
32+
"--host",
33+
dest="http_server_host",
34+
action="store",
35+
default=None,
36+
help="HTTP server host name, e.g. '127.0.0.1' or 'localhost' " f"(default: {default_http_server_host!r}).",
37+
)
38+
39+
parser.add_argument(
40+
"--port",
41+
dest="http_server_port",
42+
action="store",
43+
default=None,
44+
help="HTTP server port, e.g. '127.0.0.1' or 'localhost' " f"(default: {default_http_server_port!r}).",
45+
)
46+
47+
parser.add_argument(
48+
"--public",
49+
dest="public",
50+
action="store_true",
51+
default=False,
52+
help="Explicitly allows public access to the server and disables authorization/authentication.",
53+
)
54+
55+
parser.add_argument(
56+
"--config_path",
57+
dest="config_path",
58+
action="store",
59+
default=None,
60+
help="Path to configuration file or directory with configuration files. The path overrides "
61+
"the path defined in QSERVER_HTTP_SERVER_CONFIG environment variable. If the parameter and "
62+
"the environemnt variable is not specified, then no configuration file is loaded.",
63+
)
64+
65+
return sanitize_parsed_args(parser.parse_args())
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from .utils import get_authenticators
2+
from .settings import get_settings
3+
4+
def print_admin_api_key_if_generated(web_app, host, port):
5+
# host = host or "127.0.0.1"
6+
# port = port or 8000
7+
settings = web_app.dependency_overrides.get(get_settings, get_settings)()
8+
9+
logger.info("APP settings: %s", pprint.pformat(dict(settings)))
10+
authenticators = web_app.dependency_overrides.get(get_authenticators, get_authenticators)()
11+
if settings.allow_anonymous_access:
12+
print(
13+
"The server is running in 'public' mode, permitting open, anonymous access\n"
14+
"for reading. Any data that is not specifically controlled with an access\n"
15+
"policy will be visible to anyone who can connect to this server.\n",
16+
file=sys.stderr,
17+
)
18+
if (not authenticators) and settings.single_user_api_key_generated:
19+
print(
20+
"Navigate a web browser to:\n\n"
21+
f"http://{host}:{port}?api_key={settings.single_user_api_key}\n\n"
22+
"or connect an HTTP client to:\n\n"
23+
f"http://{host}:{port}/api?api_key={settings.single_user_api_key}\n",
24+
file=sys.stderr,
25+
)

0 commit comments

Comments
 (0)