Refactor gateway into modular architecture
Split 1878-line server.py into 15 focused modules: - config.py: all env vars and constants - database.py: schema, init, seed logic - sessions.py: session/token CRUD - proxy.py: proxy_request, SERVICE_MAP, resolve_service - responses.py: ResponseMixin for handler helpers - auth.py: login/logout/register handlers - dashboard.py: dashboard, apps, connections, pinning - command.py: AI command bar - integrations/booklore.py: auth, books, cover, import - integrations/kindle.py: send-to-kindle, file finder - integrations/karakeep.py: save/delete bookmarks - integrations/qbittorrent.py: download status - integrations/image_proxy.py: external image proxy server.py is now thin routing only (~344 lines). All routes, methods, status codes, and responses preserved exactly. Added PYTHONUNBUFFERED=1 to Dockerfile for live logging.
This commit is contained in:
36
gateway/integrations/image_proxy.py
Normal file
36
gateway/integrations/image_proxy.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
Platform Gateway — Image proxy (bypass hotlink protection).
|
||||
"""
|
||||
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
|
||||
from config import _ssl_ctx
|
||||
|
||||
|
||||
def handle_image_proxy(handler):
|
||||
"""Proxy external images to bypass hotlink protection (e.g. Reddit)."""
|
||||
qs = urllib.parse.urlparse(handler.path).query
|
||||
params = urllib.parse.parse_qs(qs)
|
||||
url = params.get("url", [None])[0]
|
||||
if not url:
|
||||
handler._send_json({"error": "Missing url parameter"}, 400)
|
||||
return
|
||||
try:
|
||||
req = urllib.request.Request(url, headers={
|
||||
"User-Agent": "Mozilla/5.0 (compatible; PlatformProxy/1.0)",
|
||||
"Accept": "image/*,*/*",
|
||||
"Referer": urllib.parse.urlparse(url).scheme + "://" + urllib.parse.urlparse(url).netloc + "/",
|
||||
})
|
||||
resp = urllib.request.urlopen(req, timeout=10, context=_ssl_ctx)
|
||||
body = resp.read()
|
||||
ct = resp.headers.get("Content-Type", "image/jpeg")
|
||||
handler.send_response(200)
|
||||
handler.send_header("Content-Type", ct)
|
||||
handler.send_header("Content-Length", len(body))
|
||||
handler.send_header("Cache-Control", "public, max-age=86400")
|
||||
handler.end_headers()
|
||||
handler.wfile.write(body)
|
||||
except Exception as e:
|
||||
print(f"[ImageProxy] Error fetching {url}: {e}")
|
||||
handler._send_json({"error": "Failed to fetch image"}, 502)
|
||||
Reference in New Issue
Block a user