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:
49
gateway/responses.py
Normal file
49
gateway/responses.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Platform Gateway — Response helpers mixed into GatewayHandler.
|
||||
"""
|
||||
|
||||
import json
|
||||
from http.cookies import SimpleCookie
|
||||
|
||||
from config import SESSION_MAX_AGE
|
||||
from sessions import get_session_user
|
||||
|
||||
|
||||
class ResponseMixin:
|
||||
"""Mixin providing response helpers for GatewayHandler."""
|
||||
|
||||
def _send_json(self, data, status=200):
|
||||
body = json.dumps(data).encode()
|
||||
self.send_response(status)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Content-Length", len(body))
|
||||
self.end_headers()
|
||||
self.wfile.write(body)
|
||||
|
||||
def _get_session_token(self):
|
||||
cookie = SimpleCookie(self.headers.get("Cookie", ""))
|
||||
if "platform_session" in cookie:
|
||||
return cookie["platform_session"].value
|
||||
auth = self.headers.get("Authorization", "")
|
||||
if auth.startswith("Bearer "):
|
||||
return auth[7:]
|
||||
return None
|
||||
|
||||
def _get_user(self):
|
||||
token = self._get_session_token()
|
||||
return get_session_user(token)
|
||||
|
||||
def _require_auth(self):
|
||||
user = self._get_user()
|
||||
if not user:
|
||||
self._send_json({"error": "Unauthorized"}, 401)
|
||||
return None
|
||||
return user
|
||||
|
||||
def _set_session_cookie(self, token):
|
||||
self.send_header("Set-Cookie",
|
||||
f"platform_session={token}; Path=/; HttpOnly; SameSite=Lax; Max-Age={SESSION_MAX_AGE}")
|
||||
|
||||
def _read_body(self):
|
||||
length = int(self.headers.get("Content-Length", 0))
|
||||
return self.rfile.read(length) if length > 0 else b""
|
||||
Reference in New Issue
Block a user