67a51c9316
IPv6 dual stack is disabled by default, and Windows resolves wildcard addresses to an IPv6 by default, so connecting through the local IPv4 address would not work. This enables IPv6 dual stacking for the HTTP server by default like done in upstream python when launching the module from CLI.
66 lines
2.2 KiB
Python
Executable file
66 lines
2.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
from http.server import HTTPServer, SimpleHTTPRequestHandler, test # type: ignore
|
|
from pathlib import Path
|
|
import os
|
|
import sys
|
|
import argparse
|
|
import contextlib
|
|
import socket
|
|
import subprocess
|
|
|
|
|
|
# See cpython GH-17851 and GH-17864.
|
|
class DualStackServer(HTTPServer):
|
|
def server_bind(self):
|
|
# Suppress exception when protocol is IPv4.
|
|
with contextlib.suppress(Exception):
|
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
|
return super().server_bind()
|
|
|
|
|
|
class CORSRequestHandler(SimpleHTTPRequestHandler):
|
|
def end_headers(self):
|
|
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
|
|
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
|
|
self.send_header("Access-Control-Allow-Origin", "*")
|
|
super().end_headers()
|
|
|
|
|
|
def shell_open(url):
|
|
if sys.platform == "win32":
|
|
os.startfile(url)
|
|
else:
|
|
opener = "open" if sys.platform == "darwin" else "xdg-open"
|
|
subprocess.call([opener, url])
|
|
|
|
|
|
def serve(root, port, run_browser):
|
|
os.chdir(root)
|
|
|
|
if run_browser:
|
|
# Open the served page in the user's default browser.
|
|
print("Opening the served URL in the default browser (use `--no-browser` or `-n` to disable this).")
|
|
shell_open(f"http://127.0.0.1:{port}")
|
|
|
|
test(CORSRequestHandler, DualStackServer, port=port)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-p", "--port", help="port to listen on", default=8060, type=int)
|
|
parser.add_argument(
|
|
"-r", "--root", help="path to serve as root (relative to `platform/web/`)", default="../../bin", type=Path
|
|
)
|
|
browser_parser = parser.add_mutually_exclusive_group(required=False)
|
|
browser_parser.add_argument(
|
|
"-n", "--no-browser", help="don't open default web browser automatically", dest="browser", action="store_false"
|
|
)
|
|
parser.set_defaults(browser=True)
|
|
args = parser.parse_args()
|
|
|
|
# Change to the directory where the script is located,
|
|
# so that the script can be run from any location.
|
|
os.chdir(Path(__file__).resolve().parent)
|
|
|
|
serve(args.root, args.port, args.browser)
|