#!/usr/bin/env python3 """Busfleet Hub — minimal HTTP registration server for kit-connect devices. Listens on :8080. Routes: GET /api/register/ — assign tunnel port, return JSON GET /health — health check """ import json import subprocess import sys from http.server import HTTPServer, BaseHTTPRequestHandler REGISTER_SH = "/opt/busfleet-hub/register.sh" class HubHandler(BaseHTTPRequestHandler): """Handle hub registration requests.""" def do_GET(self): # Route: /api/register/ if self.path.startswith("/api/register/"): device_id = self.path.split("/api/register/", 1)[1].strip("/") if not device_id: self.send_json_error(400, "Missing device ID") return try: result = subprocess.run( [REGISTER_SH, device_id], capture_output=True, text=True, timeout=15, ) status = 200 if result.returncode == 0 else 500 self.send_json(status, result.stdout.strip()) except subprocess.TimeoutExpired: self.send_json_error(504, "Registration timed out") except Exception as exc: self.send_json_error(500, str(exc)) return # Health check if self.path in ("/", "/health"): self.send_json(200, '{"status":"ok","service":"busfleet-hub"}') return self.send_json_error(404, "Not found") def send_json(self, status, body): """Send a JSON response.""" self.send_response(status) self.send_header("Content-Type", "application/json") self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() self.wfile.write(body.encode() if isinstance(body, str) else body) def send_json_error(self, status, message): """Send a JSON error response.""" self.send_json(status, json.dumps({"error": message})) def log_message(self, fmt, *args): print(f"[hub] {args[0]}", file=sys.stderr) def main(): port = int(sys.argv[1]) if len(sys.argv) > 1 else 8080 server = HTTPServer(("0.0.0.0", port), HubHandler) print(f"Busfleet Hub listening on :{port}", flush=True) try: server.serve_forever() except KeyboardInterrupt: print("\nShutting down.", flush=True) server.shutdown() if __name__ == "__main__": main()