Document who can call the loopback API and let the user pick the listen port.
This commit is contained in:
@@ -20,9 +20,12 @@ if sys.platform == "win32":
|
||||
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
||||
|
||||
HOST = "127.0.0.1"
|
||||
PORT = int(os.environ.get("FAB_PORT", "17634"))
|
||||
DEFAULT_PORT = int(os.environ.get("FAB_PORT", "17634"))
|
||||
PORT = DEFAULT_PORT
|
||||
MAX_BODY = 256 * 1024
|
||||
ALLOWED_HOSTS = {f"127.0.0.1:{PORT}", f"localhost:{PORT}"}
|
||||
HTTP_SERVER: ThreadingHTTPServer | None = None
|
||||
SERVER_LOCK = threading.Lock()
|
||||
ALLOWED_METHODS = frozenset(
|
||||
{
|
||||
"meta.ping",
|
||||
@@ -45,6 +48,45 @@ PENDING: dict[str, tuple[threading.Event, dict[str, Any]]] = {}
|
||||
PENDING_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def set_port_globals(port: int) -> None:
|
||||
global PORT, ALLOWED_HOSTS
|
||||
PORT = port
|
||||
ALLOWED_HOSTS = {f"127.0.0.1:{port}", f"localhost:{port}"}
|
||||
|
||||
|
||||
def apply_listen_port(requested: Any) -> dict[str, Any]:
|
||||
global HTTP_SERVER
|
||||
try:
|
||||
port = int(requested)
|
||||
except (TypeError, ValueError):
|
||||
return {"type": "config-result", "ok": False, "error": "invalid port"}
|
||||
if port < 1024 or port > 65535:
|
||||
return {
|
||||
"type": "config-result",
|
||||
"ok": False,
|
||||
"port": port,
|
||||
"error": "port must be 1024–65535",
|
||||
}
|
||||
with SERVER_LOCK:
|
||||
if HTTP_SERVER is not None and PORT == port:
|
||||
return {"type": "config-result", "ok": True, "port": port}
|
||||
old = HTTP_SERVER
|
||||
HTTP_SERVER = None
|
||||
if old is not None:
|
||||
old.shutdown()
|
||||
old.server_close()
|
||||
try:
|
||||
set_port_globals(port)
|
||||
HTTP_SERVER = ThreadingHTTPServer((HOST, port), Handler)
|
||||
except OSError as exc:
|
||||
return {"type": "config-result", "ok": False, "port": port, "error": str(exc)}
|
||||
threading.Thread(
|
||||
target=HTTP_SERVER.serve_forever, name="fab-http", daemon=True
|
||||
).start()
|
||||
log(f"listening on http://{HOST}:{port}")
|
||||
return {"type": "config-result", "ok": True, "port": port}
|
||||
|
||||
|
||||
def log(msg: str) -> None:
|
||||
sys.stderr.write(msg + "\n")
|
||||
sys.stderr.flush()
|
||||
@@ -252,6 +294,9 @@ def stdin_loop() -> None:
|
||||
break
|
||||
if message is None:
|
||||
break
|
||||
if message.get("type") == "config":
|
||||
send_to_extension(apply_listen_port(message.get("port")))
|
||||
continue
|
||||
req_id = str(message.get("id") or "")
|
||||
with PENDING_LOCK:
|
||||
pending = PENDING.pop(req_id, None)
|
||||
@@ -265,10 +310,9 @@ def stdin_loop() -> None:
|
||||
|
||||
def main() -> int:
|
||||
threading.Thread(target=stdin_loop, name="fab-stdin", daemon=True).start()
|
||||
server = ThreadingHTTPServer((HOST, PORT), Handler)
|
||||
log(f"listening on http://{HOST}:{PORT}")
|
||||
apply_listen_port(DEFAULT_PORT)
|
||||
try:
|
||||
server.serve_forever()
|
||||
threading.Event().wait()
|
||||
except KeyboardInterrupt:
|
||||
return 0
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user