-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathserve_ui.py
More file actions
83 lines (68 loc) · 2.78 KB
/
Copy pathserve_ui.py
File metadata and controls
83 lines (68 loc) · 2.78 KB
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
"""Serve only the public UI assets required by VibeCoding Controller Hub."""
from __future__ import annotations
import os
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import unquote, urlparse
HOST = "127.0.0.1"
PORT = 4173
ROOT = os.path.dirname(os.path.abspath(__file__))
PUBLIC_ASSETS = {
"/": ("index.html", "text/html; charset=utf-8"),
"/index.html": ("index.html", "text/html; charset=utf-8"),
"/app.js": ("app.js", "text/javascript; charset=utf-8"),
"/styles.css": ("styles.css", "text/css; charset=utf-8"),
"/assets/dualsense-wireframe.png": ("assets/dualsense-wireframe.png", "image/png"),
}
def resolve_asset(raw_path: str) -> tuple[str, str] | None:
"""Resolve an exact allowlisted URL path to a local asset."""
request_path = unquote(urlparse(raw_path).path)
asset = PUBLIC_ASSETS.get(request_path)
if asset is None:
return None
relative_path, content_type = asset
return os.path.join(ROOT, *relative_path.split("/")), content_type
class PublicUiHandler(BaseHTTPRequestHandler):
server_version = "DS5VibeHubUI/1.0"
def _send_asset(self, include_body: bool) -> None:
asset = resolve_asset(self.path)
if asset is None:
self.send_error(HTTPStatus.NOT_FOUND)
return
path, content_type = asset
try:
with open(path, "rb") as stream:
body = stream.read()
except OSError:
self.send_error(HTTPStatus.NOT_FOUND)
return
self.send_response(HTTPStatus.OK)
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(body)))
self.send_header("Cache-Control", "no-store")
self.send_header("X-Content-Type-Options", "nosniff")
self.send_header("Referrer-Policy", "no-referrer")
self.send_header(
"Content-Security-Policy",
"default-src 'self'; connect-src http://127.0.0.1:37845; "
"img-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; "
"base-uri 'none'; frame-ancestors 'none'",
)
self.end_headers()
if include_body:
self.wfile.write(body)
def do_GET(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API
self._send_asset(include_body=True)
def do_HEAD(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API
self._send_asset(include_body=False)
def main() -> None:
server = ThreadingHTTPServer((HOST, PORT), PublicUiHandler)
print(f"VibeCoding Controller Hub UI listening on http://{HOST}:{PORT}")
try:
server.serve_forever()
except KeyboardInterrupt:
pass
finally:
server.server_close()
if __name__ == "__main__":
main()