#!/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()