#!/usr/bin/env python3
"""Minimal static file server WITH HTTP Range support (resumable downloads).
Serves the CWD on 127.0.0.1:8088 (localhost-only; Tailscale Funnel proxies it)."""
import os, http.server, socketserver
from functools import partial

class RangeHandler(http.server.SimpleHTTPRequestHandler):
    def send_head(self):
        rng = self.headers.get("Range")
        if not rng:
            return super().send_head()
        path = self.translate_path(self.path)
        if not os.path.isfile(path):
            return super().send_head()  # dirs/listings fall through
        try:
            size = os.path.getsize(path)
            unit, _, rspec = rng.partition("=")
            start_s, _, end_s = rspec.partition("-")
            start = int(start_s) if start_s else 0
            end = int(end_s) if end_s else size - 1
            end = min(end, size - 1)
            if unit.strip() != "bytes" or start > end:
                self.send_error(416); return None
        except (ValueError, OSError):
            return super().send_head()
        f = open(path, "rb"); f.seek(start)
        self.send_response(206)
        self.send_header("Content-Type", self.guess_type(path))
        self.send_header("Accept-Ranges", "bytes")
        self.send_header("Content-Range", f"bytes {start}-{end}/{size}")
        self.send_header("Content-Length", str(end - start + 1))
        self.end_headers()
        self._range = (start, end)
        return f

    def copyfile(self, src, dst):
        if not hasattr(self, "_range"):
            return super().copyfile(src, dst)
        start, end = self._range; del self._range
        remaining = end - start + 1
        while remaining > 0:
            chunk = src.read(min(1 << 20, remaining))
            if not chunk: break
            dst.write(chunk); remaining -= len(chunk)

class Threaded(socketserver.ThreadingMixIn, http.server.HTTPServer):
    daemon_threads = True

if __name__ == "__main__":
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    Threaded(("127.0.0.1", 8088), partial(RangeHandler)).serve_forever()
