"""Debug reverse-proxy: http://0.0.0.0:8099 → https://api.goon-foss.org Emulator app (via http://10.0.2.2:8099, cleartext dozwolony w NSC dla 10.0.2.2) uderza ten proxy → forward do prawdziwego backendu. Loguje każdy request: method, path, headers (X-API-Key, X-App-Signature), response status. Cel: zdiagnozować czy app fetch w ogóle działa + jakie headers wysyła. """ import http.server import socketserver import ssl import urllib.request import urllib.error UPSTREAM = "https://api.goon-foss.org" PORT = 8099 class ProxyHandler(http.server.BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" def _proxy(self, method): body_len = int(self.headers.get("Content-Length", 0)) body = self.rfile.read(body_len) if body_len else None print(f"\n>>> {method} {self.path}") for h in ("X-API-Key", "X-App-Signature", "Authorization", "User-Agent", "Accept", "Content-Type"): if h in self.headers: val = self.headers[h] if h == "X-App-Signature": print(f" {h}: {val[:20]}...{val[-8:]} (len={len(val)})") elif h == "X-API-Key": print(f" {h}: {val[:8]}... (len={len(val)})") else: print(f" {h}: {val}") url = UPSTREAM + self.path req = urllib.request.Request(url, data=body, method=method) for k, v in self.headers.items(): if k.lower() not in ("host", "content-length", "connection", "accept-encoding"): req.add_header(k, v) ctx = ssl.create_default_context() try: with urllib.request.urlopen(req, context=ctx, timeout=30) as resp: data = resp.read() print(f"<<< {resp.status} ({len(data)} bytes)") self.send_response(resp.status) for k, v in resp.headers.items(): if k.lower() not in ("transfer-encoding", "connection", "content-encoding", "content-length"): self.send_header(k, v) self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) except urllib.error.HTTPError as e: data = e.read() print(f"<<< HTTP {e.code} ({len(data)} bytes): {data[:200]}") self.send_response(e.code) self.send_header("Content-Type", e.headers.get("Content-Type", "application/json")) self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) except Exception as e: print(f"<<< PROXY ERROR: {type(e).__name__}: {e}") msg = f'{{"detail":"proxy error: {e}"}}'.encode() self.send_response(502) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(msg))) self.end_headers() self.wfile.write(msg) def do_GET(self): self._proxy("GET") def do_POST(self): self._proxy("POST") def do_DELETE(self): self._proxy("DELETE") def log_message(self, *args): pass # silence default logging class ThreadingServer(socketserver.ThreadingMixIn, http.server.HTTPServer): daemon_threads = True if __name__ == "__main__": print(f"debug proxy: http://0.0.0.0:{PORT} -> {UPSTREAM}") print(f"emulator app should point to http://10.0.2.2:{PORT}") ThreadingServer(("0.0.0.0", PORT), ProxyHandler).serve_forever()