import json import os from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.error import HTTPError, URLError from urllib.request import Request, urlopen TARGET = os.getenv("GROBID_TARGET", "http://127.0.0.1:8070").rstrip("/") PORT = int(os.getenv("PORT", "7860")) HOP_BY_HOP = { "connection", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailers", "transfer-encoding", "upgrade", } class ProxyHandler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" def _forward(self): content_length = int(self.headers.get("Content-Length", "0") or "0") body = self.rfile.read(content_length) if content_length > 0 else None upstream_url = f"{TARGET}{self.path}" headers = {} for k, v in self.headers.items(): lk = k.lower() if lk == "host" or lk in HOP_BY_HOP: continue headers[k] = v req = Request(upstream_url, data=body, headers=headers, method=self.command) try: with urlopen(req, timeout=180) as resp: data = resp.read() self.send_response(resp.getcode()) for k, v in resp.getheaders(): if k.lower() in HOP_BY_HOP: continue self.send_header(k, v) self.send_header("Content-Length", str(len(data))) self.end_headers() if data: self.wfile.write(data) except HTTPError as e: data = e.read() if hasattr(e, "read") else b"" self.send_response(e.code) for k, v in e.headers.items(): if k.lower() in HOP_BY_HOP: continue self.send_header(k, v) self.send_header("Content-Length", str(len(data))) self.end_headers() if data: self.wfile.write(data) except URLError: data = json.dumps({"error": "Upstream GROBID unavailable"}).encode("utf-8") self.send_response(502) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) def do_GET(self): self._forward() def do_POST(self): self._forward() def do_PUT(self): self._forward() def do_DELETE(self): self._forward() def do_PATCH(self): self._forward() def do_OPTIONS(self): self._forward() if __name__ == "__main__": server = HTTPServer(("0.0.0.0", PORT), ProxyHandler) print(f"Proxy listening on :{PORT}, forwarding to {TARGET}") server.serve_forever()