server.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #!/usr/bin/env python
  2. # Based on http/server.py from Python
  3. from argparse import ArgumentParser
  4. import contextlib
  5. from http.server import SimpleHTTPRequestHandler
  6. from http.server import ThreadingHTTPServer
  7. import socket
  8. from socketserver import TCPServer
  9. class MyHTTPRequestHandler(SimpleHTTPRequestHandler):
  10. extensions_map = {
  11. ".manifest": "text/cache-manifest",
  12. ".html": "text/html",
  13. ".png": "image/png",
  14. ".jpg": "image/jpg",
  15. ".svg": "image/svg+xml",
  16. ".css": "text/css",
  17. ".js": "application/x-javascript",
  18. ".wasm": "application/wasm",
  19. "": "application/octet-stream",
  20. }
  21. def end_headers(self):
  22. self.send_my_headers()
  23. SimpleHTTPRequestHandler.end_headers(self)
  24. def send_my_headers(self):
  25. self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
  26. self.send_header("Pragma", "no-cache")
  27. self.send_header("Expires", "0")
  28. def serve_forever(port: int, ServerClass):
  29. handler = MyHTTPRequestHandler
  30. addr = ("0.0.0.0", port)
  31. HandlerClass = SimpleHTTPRequestHandler
  32. with ServerClass(addr, handler) as httpd:
  33. host, port = httpd.socket.getsockname()[:2]
  34. url_host = f"[{host}]" if ":" in host else host
  35. print(f"Serving HTTP on {host} port {port} (http://{url_host}:{port}/) ...")
  36. try:
  37. httpd.serve_forever()
  38. except KeyboardInterrupt:
  39. print("\nKeyboard interrupt received, exiting.")
  40. return 0
  41. def main():
  42. parser = ArgumentParser(allow_abbrev=False)
  43. parser.add_argument("port", nargs="?", type=int, default=8080)
  44. parser.add_argument("-d", dest="directory", type=str, default=None)
  45. args = parser.parse_args()
  46. class DualStackServer(ThreadingHTTPServer):
  47. def server_bind(self):
  48. # suppress exception when protocol is IPv4
  49. with contextlib.suppress(Exception):
  50. self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
  51. return super().server_bind()
  52. def finish_request(self, request, client_address):
  53. self.RequestHandlerClass(request, client_address, self, directory=args.directory)
  54. return serve_forever(
  55. port=args.port,
  56. ServerClass=DualStackServer,
  57. )
  58. if __name__ == "__main__":
  59. raise SystemExit(main())