MCPcopy Create free account
hub / github.com/coi/coi / DevHandler

Class DevHandler

scripts/dev_server.py:30–107  ·  view source on GitHub ↗

HTTP handler with SPA routing and optional hot reload support.

Source from the content-addressed store, hash-verified

28
29
30class DevHandler(http.server.SimpleHTTPRequestHandler):
31 """HTTP handler with SPA routing and optional hot reload support."""
32
33 def log_message(self, format, *args):
34 pass # Suppress logging
35
36 def do_GET(self):
37 global hot_reload_enabled
38
39 # Handle SSE endpoint for hot reload
40 if self.path == '/__hot_reload' and hot_reload_enabled:
41 self.handle_sse()
42 return
43
44 path = self.translate_path(self.path)
45
46 if os.path.isfile(path):
47 if path.endswith('.html') and hot_reload_enabled:
48 self.serve_html_with_reload(path)
49 else:
50 super().do_GET()
51 return
52
53 # SPA fallback
54 self.path = '/index.html'
55 index_path = self.translate_path(self.path)
56 if os.path.isfile(index_path):
57 if hot_reload_enabled:
58 self.serve_html_with_reload(index_path)
59 else:
60 super().do_GET()
61 else:
62 self.send_error(404)
63
64 def serve_html_with_reload(self, path):
65 """Inject hot reload script into HTML."""
66 try:
67 with open(path, 'rb') as f:
68 content = f.read()
69
70 script = b'''<script>(function(){var k='__coi_scroll';if('scrollRestoration' in history)history.scrollRestoration='manual';var s=sessionStorage.getItem(k);if(s){sessionStorage.removeItem(k);var y=parseInt(s);var n=0;function r(){if(n++>30)return;window.scrollTo(0,y);if(Math.abs(window.scrollY-y)>1)setTimeout(r,60)}window.addEventListener('load',function(){requestAnimationFrame(r)});document.addEventListener('DOMContentLoaded',function(){requestAnimationFrame(r)})}var e=new EventSource('/__hot_reload');e.onmessage=function(m){if(m.data==='reload'){sessionStorage.setItem(k,window.scrollY||document.documentElement.scrollTop);location.reload()}};e.onerror=function(){console.log('[Coi] Reconnecting...')}})();</script></body>'''
71 content = content.replace(b'</body>', script)
72
73 self.send_response(200)
74 self.send_header('Content-Type', 'text/html; charset=utf-8')
75 self.send_header('Content-Length', len(content))
76 self.send_header('Cache-Control', 'no-cache')
77 self.end_headers()
78 self.wfile.write(content)
79 except Exception as e:
80 self.send_error(500, str(e))
81
82 def handle_sse(self):
83 """Server-Sent Events for hot reload."""
84 self.send_response(200)
85 self.send_header('Content-Type', 'text/event-stream')
86 self.send_header('Cache-Control', 'no-cache')
87 self.send_header('Connection', 'keep-alive')

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected