~kris/9p

krisyotam.net

ref: 8bfa4b74cf61e74b5d7c8df7d0b0bceefe2569fe krisyotam.net/serve.py -rw-r--r-- 3.2 KiB
8bfa4b74 — Kris Yotam ci: declare SourceHut source for push builds a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/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()