pyodide/pyodide-test-runner/pyodide_test_runner/server.py

83 lines
2.2 KiB
Python
Raw Normal View History

import contextlib
import http.server
import multiprocessing
import os
import pathlib
import queue
import shutil
import socketserver
import sys
import tempfile
@contextlib.contextmanager
def spawn_web_server(dist_dir):
tmp_dir = tempfile.mkdtemp()
log_path = pathlib.Path(tmp_dir) / "http-server.log"
q: multiprocessing.Queue[str] = multiprocessing.Queue()
p = multiprocessing.Process(target=run_web_server, args=(q, log_path, dist_dir))
try:
p.start()
port = q.get()
hostname = "127.0.0.1"
print(
f"Spawning webserver at http://{hostname}:{port} "
f"(see logs in {log_path})"
)
yield hostname, port, log_path
finally:
q.put("TERMINATE")
p.join()
shutil.rmtree(tmp_dir)
def run_web_server(q, log_filepath, dist_dir):
"""Start the HTTP web server
Parameters
----------
q : Queue
communication queue
log_path : pathlib.Path
path to the file where to store the logs
"""
os.chdir(dist_dir)
log_fh = log_filepath.open("w", buffering=1)
sys.stdout = log_fh
sys.stderr = log_fh
class Handler(http.server.SimpleHTTPRequestHandler):
def log_message(self, format_, *args):
print(
"[%s] source: %s:%s - %s"
% (self.log_date_time_string(), *self.client_address, format_ % args)
)
def end_headers(self):
# Enable Cross-Origin Resource Sharing (CORS)
self.send_header("Access-Control-Allow-Origin", "*")
super().end_headers()
with socketserver.TCPServer(("", 0), Handler) as httpd:
host, port = httpd.server_address
print(f"Starting webserver at http://{host}:{port}")
httpd.server_name = "test-server" # type: ignore[attr-defined]
httpd.server_port = port # type: ignore[attr-defined]
q.put(port)
def service_actions():
try:
if q.get(False) == "TERMINATE":
print("Stopping server...")
sys.exit(0)
except queue.Empty:
pass
httpd.service_actions = service_actions # type: ignore[assignment]
httpd.serve_forever()