Skip to content

Instantly share code, notes, and snippets.

@a5ync
Last active January 31, 2025 18:18
Show Gist options
  • Select an option

  • Save a5ync/7e76bfc95f87273c83c273c5de9fe990 to your computer and use it in GitHub Desktop.

Select an option

Save a5ync/7e76bfc95f87273c83c273c5de9fe990 to your computer and use it in GitHub Desktop.
Static file server with automatic decompression for *.html.gz files.
import http.server
import os
import gzip
import argparse
# Default Constants
DEFAULT_PORT = 8123
DEFAULT_BASE_DIR = "./snapshot"
DEFAULT_ROUTE = "/snapshot-fast"
# Allow overriding via command-line arguments
parser = argparse.ArgumentParser(
description="Start a simple HTTP server with gzip handling.", add_help=True
)
parser.add_argument(
"--port",
type=int,
help=f"Port number (default: {DEFAULT_PORT})",
default=DEFAULT_PORT,
)
parser.add_argument(
"--base-dir",
type=str,
help=f"Base directory for serving files (default: {DEFAULT_BASE_DIR})",
default=DEFAULT_BASE_DIR,
)
parser.add_argument(
"--route",
type=str,
help=f"Route prefix (default: {DEFAULT_ROUTE})",
default=DEFAULT_ROUTE,
)
args = parser.parse_args()
PORT = args.port
BASE_DIR = args.base_dir.rstrip("/") # Ensure no trailing slash
ROUTE = args.route
print(
f"Starting server on port {PORT} with base directory {BASE_DIR} and route {ROUTE}"
)
class CustomHandler(http.server.SimpleHTTPRequestHandler):
def translate_path(self, path):
"""Remap /route to base_dir and enforce directory restrictions."""
if not path.startswith(ROUTE):
self.send_error(403, "Access denied")
return None
if path.startswith(ROUTE):
path = path[len(ROUTE) :]
# Convert to absolute path
full_path = os.path.abspath(os.path.join(BASE_DIR, path.lstrip("/")))
realpath = os.path.realpath(full_path)
# Ensure the requested path is within ROOT_DIRECTORY
if not realpath.startswith(BASE_DIR):
self.send_error(403, "Access denied")
return None
return full_path
def do_GET(self):
"""Intercept .gz files, decompress, and serve as HTML securely."""
file_path = self.translate_path(self.path)
if file_path is None:
return # Access was denied in translate_path
if self.path.endswith(".gz") and os.path.exists(file_path):
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.send_header(
"Content-Disposition", "inline"
) # Force display in browser
self.end_headers()
# Read and decompress .gz file
with gzip.open(file_path, "rb") as f:
self.wfile.write(f.read()) # Send decompressed content
return
# Default handling for other files
super().do_GET()
# PORT = 8123
if __name__ == "__main__":
server_address = ("", PORT)
httpd = http.server.HTTPServer(server_address, CustomHandler)
print(f"Serving HTTP on port {PORT} (http://0.0.0.0:{PORT}{ROUTE}/...)")
httpd.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment