#!/usr/bin/env python3 """Local dev server for werc. Calls werc.rc as CGI.""" import http.server import subprocess import sys import os import urllib.parse PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8000 WERC_ROOT = os.path.dirname(os.path.abspath(__file__)) PLAN9 = "/usr/lib/plan9" class WercHandler(http.server.BaseHTTPRequestHandler): def do_GET(self): # Serve static files from pub/ parsed = urllib.parse.urlparse(self.path) if parsed.path == "/favicon.ico": fpath = os.path.join(WERC_ROOT, "pub", "favicon.ico") if os.path.isfile(fpath): self.send_response(200) self.send_header("Content-Type", "image/x-icon") self.end_headers() with open(fpath, "rb") as f: self.wfile.write(f.read()) return if parsed.path.startswith("/pub/") or parsed.path.startswith("/images/"): fpath = os.path.join(WERC_ROOT, parsed.path.lstrip("/")) if os.path.isfile(fpath): ext = os.path.splitext(fpath)[1] ct = {".css": "text/css", ".js": "application/javascript", ".png": "image/png", ".ico": "image/x-icon", ".jpeg": "image/jpeg", ".jpg": "image/jpeg"}.get(ext, "application/octet-stream") self.send_response(200) self.send_header("Content-Type", ct) self.end_headers() with open(fpath, "rb") as f: self.wfile.write(f.read()) return env = os.environ.copy() env.update({ "PLAN9": PLAN9, "PATH": f"{PLAN9}/bin:{WERC_ROOT}/bin:{WERC_ROOT}/bin/contrib:/bin:/usr/bin", "SERVER_NAME": "plan9.krisyotam.com", "SERVER_PORT": str(PORT), "REQUEST_METHOD": "GET", "REQUEST_URI": self.path, "PATH_INFO": parsed.path, "QUERY_STRING": parsed.query or "", "HTTP_COOKIE": self.headers.get("Cookie", ""), "HTTP_HOST": self.headers.get("Host", "plan9.krisyotam.com"), }) result = subprocess.run( [f"{PLAN9}/bin/rc", "./werc.rc"], cwd=os.path.join(WERC_ROOT, "bin"), env=env, capture_output=True, timeout=5 ) output = result.stdout if not output: self.send_response(500) self.end_headers() self.wfile.write(result.stderr or b"empty response") return # Split CGI headers from body parts = output.split(b"\n\n", 1) if len(parts) == 2: headers, body = parts else: headers, body = b"", output self.send_response(200) for line in headers.decode(errors="replace").splitlines(): if ":" in line: k, v = line.split(":", 1) self.send_header(k.strip(), v.strip()) self.end_headers() self.wfile.write(body) def log_message(self, fmt, *args): print(f" {args[0]}") print(f"werc serving plan9.krisyotam.com at http://localhost:{PORT}") http.server.HTTPServer(("", PORT), WercHandler).serve_forever()