From 2e823c9d16fd0086e1c0003ad20eaff4edcb3594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IT=E7=8B=97?= Date: Fri, 24 Jul 2026 20:23:39 +0800 Subject: [PATCH] v1.1.0: fix /crawl/* GET routes (move handlers to do_GET start) Bug: /crawl/status and /crawl/download handlers were placed after return statement in do_GET, making them dead code. Static file check would 404 + fall through to index.html (HTML 200), masking the real issue. Fix: move /crawl/* API handlers to top of do_GET, before static file check. Now /crawl/status returns JSON, /crawl/download returns file with proper Content-Disposition. Also: cleanup duplicate def do_GET introduced by earlier patch. Reported by: Hermes (@Ir_workbot) --- server.py | 105 ++++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 58 deletions(-) diff --git a/server.py b/server.py index 6c07e10..9ca8dea 100644 --- a/server.py +++ b/server.py @@ -313,9 +313,52 @@ class Handler(BaseHTTPRequestHandler): self.wfile.write(json.dumps(data).encode()) def do_GET(self): - # Static file serving: or /url2pdf-tools/ → /opt/url2pdf/ - # (nginx strips /url2pdf prefix; we accept both with and without it) - # Static file serving: or /url2pdf-tools/ -> /opt/url2pdf/ + # 1. /crawl/status?job=ID - poll job status + if self.path.startswith("/crawl/status"): + qs = urllib.parse.urlparse(self.path).query + params = urllib.parse.parse_qs(qs) + job = params.get("job", [None])[0] + if not job: + self._json(400, {"error": "Missing job"}) + return + sp = os.path.join(JOBS_DIR, job, "status.json") + if os.path.exists(sp): + with open(sp) as f: + self._json(200, json.load(f)) + else: + self._json(200, {"status": "pending"}) + return + + # 2. /crawl/download?job=ID&format=md|pdf - download output + if self.path.startswith("/crawl/download"): + qs = urllib.parse.urlparse(self.path).query + params = urllib.parse.parse_qs(qs) + job = params.get("job", [None])[0] + fmt = params.get("format", ["pdf"])[0] + if not job: + self.send_error(400) + return + jdir = os.path.join(JOBS_DIR, job) + if fmt == "md": + fp = os.path.join(jdir, "output.md") + ct = "text/markdown" + else: + fp = os.path.join(jdir, "output.pdf") + ct = "application/pdf" + if not os.path.exists(fp): + self.send_error(404, "Not found") + return + with open(fp, "rb") as f: + data = f.read() + self.send_response(200) + self.send_header("Content-Type", ct) + self.send_header("Content-Disposition", f'attachment; filename="{job}.{fmt}"') + self.send_header("Content-Length", str(len(data))) + self.end_headers() + self.wfile.write(data) + return + + # 3. Static file serving: or /url2pdf-tools/ -> /opt/url2pdf/ # (nginx strips /url2pdf prefix; we accept both with and without it) if self.path.startswith("/url2pdf-tools/"): rel = self.path[len("/url2pdf-tools/"):] @@ -332,7 +375,6 @@ class Handler(BaseHTTPRequestHandler): self.send_error(400, "Bad path") return fp = os.path.join("/opt/url2pdf", safe) - fp = os.path.join("/opt/url2pdf", safe) if os.path.isfile(fp): import mimetypes ct, _ = mimetypes.guess_type(fp) @@ -346,63 +388,10 @@ class Handler(BaseHTTPRequestHandler): self.end_headers() self.wfile.write(data) return - # file not found under /opt/url2pdf - fall through to API or HTML fallback + # file not found under /opt/url2pdf self.send_error(404, "Not found: " + fp) return - if self.path.startswith("/crawl/status"): - qs = urllib.parse.urlparse(self.path).query - params = urllib.parse.parse_qs(qs) - job = params.get("job", [None])[0] - if not job: - self._json(400, {"error": "Missing job"}) - return - sp = os.path.join(JOBS_DIR, job, "status.json") - if os.path.exists(sp): - with open(sp) as f: - self._json(200, json.load(f)) - else: - self._json(200, {"status": "pending"}) - return - - - if self.path.startswith("/crawl/download"): - qs = urllib.parse.urlparse(self.path).query - params = urllib.parse.parse_qs(qs) - job = params.get("job", [None])[0] - fmt = params.get("format", ["pdf"])[0] - if not job: - self.send_error(400) - return - - jdir = os.path.join(JOBS_DIR, job) - if fmt == "md": - fp = os.path.join(jdir, "output.md") - ct = "text/markdown" - else: - fp = os.path.join(jdir, "output.pdf") - ct = "application/pdf" - - if not os.path.exists(fp): - self.send_error(404, "Not found") - return - - with open(fp, "rb") as f: - data = f.read() - self.send_response(200) - self.send_header("Content-Type", ct) - self.send_header("Content-Disposition", f'attachment; filename="{job}.{fmt}"') - self.send_header("Content-Length", str(len(data))) - self.end_headers() - self.wfile.write(data) - return - - # Serve HTML - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.end_headers() - self.wfile.write(HTML.encode()) - def do_POST(self): length = int(self.headers.get("Content-Length", 0)) body = self.rfile.read(length)