mirror of https://github.com/pyodide/pyodide.git
83 lines
2.2 KiB
Python
83 lines
2.2 KiB
Python
![]() |
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()
|