mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-11-04 01:34:38 +00:00 
			
		
		
		
	This allows to 'mount' the SDL source directory on http://localhost:8080/SDL. This is useful for debugging emscripten applications in the browser. Build SDL with "-gsource-map -ffile-prefix-map=/path/to/SDL:/SDL" to configure the URL where the source code must be available.
		
			
				
	
	
		
			103 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/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())
 |