diff options
Diffstat (limited to 'playground')
| -rw-r--r-- | playground/web/server.py | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/playground/web/server.py b/playground/web/server.py new file mode 100644 index 0000000..56ae429 --- /dev/null +++ b/playground/web/server.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +""" +Playground demo service — stdlib HTTP status page on port 9090. +Registered behind doot's auth layer at /playground/. +Start: python3 playground/web/server.py +""" + +import http.server +import json +import os +import platform +import socket +import time +from datetime import datetime, timezone + +START_TIME = time.monotonic() +PORT = int(os.environ.get("PLAYGROUND_PORT", "9090")) + +STATUS_HTML = """\ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<title>Playground — System Status</title> +<style> + body {{ font-family: monospace; background: #0f111a; color: #cdd6f4; margin: 0; padding: 2rem; }} + h1 {{ color: #89b4fa; margin-bottom: 0.25rem; }} + .subtitle {{ color: #6c7086; font-size: 0.85rem; margin-bottom: 2rem; }} + table {{ border-collapse: collapse; width: 100%; max-width: 640px; }} + td {{ padding: 0.4rem 0.8rem; border-bottom: 1px solid #313244; }} + td:first-child {{ color: #a6e3a1; width: 200px; }} + .badge {{ display: inline-block; background: #1e6e3a; color: #a6e3a1; + padding: 0.1rem 0.5rem; border-radius: 3px; font-size: 0.8rem; }} +</style> +</head> +<body> +<h1>Playground</h1> +<p class="subtitle">doot service gateway demo — authenticated via doot session</p> +<table> + <tr><td>status</td><td><span class="badge">ok</span></td></tr> + <tr><td>hostname</td><td>{hostname}</td></tr> + <tr><td>python</td><td>{python}</td></tr> + <tr><td>platform</td><td>{platform}</td></tr> + <tr><td>uptime</td><td>{uptime}</td></tr> + <tr><td>server time</td><td>{now}</td></tr> + <tr><td>pid</td><td>{pid}</td></tr> + <tr><td>port</td><td>{port}</td></tr> +</table> +</body> +</html> +""" + + +def _uptime() -> str: + elapsed = int(time.monotonic() - START_TIME) + h, rem = divmod(elapsed, 3600) + m, s = divmod(rem, 60) + return f"{h}h {m}m {s}s" + + +class Handler(http.server.BaseHTTPRequestHandler): + def log_message(self, fmt, *args): # quieter logs + print(f"{self.address_string()} {fmt % args}") + + def do_GET(self): + if self.path in ("/health", "/health/"): + body = json.dumps({"status": "ok", "uptime": _uptime()}).encode() + self._respond(200, "application/json", body) + return + + html = STATUS_HTML.format( + hostname=socket.gethostname(), + python=platform.python_version(), + platform=platform.system() + " " + platform.release(), + uptime=_uptime(), + now=datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC"), + pid=os.getpid(), + port=PORT, + ).encode() + self._respond(200, "text/html; charset=utf-8", html) + + def _respond(self, code, content_type, body): + self.send_response(code) + self.send_header("Content-Type", content_type) + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + +if __name__ == "__main__": + server = http.server.HTTPServer(("127.0.0.1", PORT), Handler) + print(f"playground listening on http://127.0.0.1:{PORT} (pid {os.getpid()})") + server.serve_forever() |
