summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/emscripten/server.py
blob: 103d1645c0ac7c6963e77389f5faff6b20722b19 (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env python

# Based on http/server.py from Python

from argparse import ArgumentParser
import contextlib
from http.server import SimpleHTTPRequestHandler
from http.server import ThreadingHTTPServer
import os
import socket


class MyHTTPRequestHandler(SimpleHTTPRequestHandler):
    extensions_map = {
        ".manifest": "text/cache-manifest",
        ".html": "text/html",
        ".png": "image/png",
        ".jpg": "image/jpg",
        ".svg":	"image/svg+xml",
        ".css":	"text/css",
        ".js":	"application/x-javascript",
        ".wasm": "application/wasm",
        "": "application/octet-stream",
    }

    def __init__(self, *args, maps=None, **kwargs):
        self.maps = maps or []
        SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)

    def end_headers(self):
        self.send_my_headers()
        SimpleHTTPRequestHandler.end_headers(self)

    def send_my_headers(self):
        self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
        self.send_header("Pragma", "no-cache")
        self.send_header("Expires", "0")

    def translate_path(self, path):
        for map_path, map_prefix in self.maps:
            if path.startswith(map_prefix):
                res = os.path.join(map_path, path.removeprefix(map_prefix).lstrip("/"))
                break
        else:
            res = super().translate_path(path)
        return res


def serve_forever(port: int, ServerClass):
    handler = MyHTTPRequestHandler

    addr = ("0.0.0.0", port)
    with ServerClass(addr, handler) as httpd:
        host, port = httpd.socket.getsockname()[:2]
        url_host = f"[{host}]" if ":" in host else host
        print(f"Serving HTTP on {host} port {port} (http://{url_host}:{port}/) ...")
        try:
            httpd.serve_forever()
        except KeyboardInterrupt:
            print("\nKeyboard interrupt received, exiting.")
            return 0


def main():
    parser = ArgumentParser(allow_abbrev=False)
    parser.add_argument("port", nargs="?", type=int, default=8080)
    parser.add_argument("-d", dest="directory", type=str, default=None)
    parser.add_argument("--map", dest="maps", nargs="+", type=str, help="Mappings, used as e.g. \"$HOME/projects/SDL:/sdl\"")
    args = parser.parse_args()

    maps = []
    for m in args.maps:
        try:
            path, uri  = m.split(":", 1)
        except ValueError:
            parser.error(f"Invalid mapping: \"{m}\"")
        maps.append((path, uri))

    class DualStackServer(ThreadingHTTPServer):
        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()

        def finish_request(self, request, client_address):
            self.RequestHandlerClass(
                request,
                client_address,
                self,
                directory=args.directory,
                maps=maps,
            )

    return serve_forever(
        port=args.port,
        ServerClass=DualStackServer,
    )


if __name__ == "__main__":
    raise SystemExit(main())