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)
This commit is contained in:
@@ -313,9 +313,52 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.wfile.write(json.dumps(data).encode())
|
self.wfile.write(json.dumps(data).encode())
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
# Static file serving: <file> or /url2pdf-tools/<file> → /opt/url2pdf/<file>
|
# 1. /crawl/status?job=ID - poll job status
|
||||||
# (nginx strips /url2pdf prefix; we accept both with and without it)
|
if self.path.startswith("/crawl/status"):
|
||||||
# Static file serving: <file> or /url2pdf-tools/<file> -> /opt/url2pdf/<file>
|
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: <file> or /url2pdf-tools/<file> -> /opt/url2pdf/<file>
|
||||||
# (nginx strips /url2pdf prefix; we accept both with and without it)
|
# (nginx strips /url2pdf prefix; we accept both with and without it)
|
||||||
if self.path.startswith("/url2pdf-tools/"):
|
if self.path.startswith("/url2pdf-tools/"):
|
||||||
rel = self.path[len("/url2pdf-tools/"):]
|
rel = self.path[len("/url2pdf-tools/"):]
|
||||||
@@ -332,7 +375,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.send_error(400, "Bad path")
|
self.send_error(400, "Bad path")
|
||||||
return
|
return
|
||||||
fp = os.path.join("/opt/url2pdf", safe)
|
fp = os.path.join("/opt/url2pdf", safe)
|
||||||
fp = os.path.join("/opt/url2pdf", safe)
|
|
||||||
if os.path.isfile(fp):
|
if os.path.isfile(fp):
|
||||||
import mimetypes
|
import mimetypes
|
||||||
ct, _ = mimetypes.guess_type(fp)
|
ct, _ = mimetypes.guess_type(fp)
|
||||||
@@ -346,63 +388,10 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(data)
|
self.wfile.write(data)
|
||||||
return
|
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)
|
self.send_error(404, "Not found: " + fp)
|
||||||
return
|
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):
|
def do_POST(self):
|
||||||
length = int(self.headers.get("Content-Length", 0))
|
length = int(self.headers.get("Content-Length", 0))
|
||||||
body = self.rfile.read(length)
|
body = self.rfile.read(length)
|
||||||
|
|||||||
Reference in New Issue
Block a user