| 41 | |
| 42 | |
| 43 | class GeminiHandler(BaseHTTPRequestHandler): |
| 44 | def log_message(self, fmt, *args): |
| 45 | log(fmt % args) |
| 46 | |
| 47 | def send_json(self, data, status=200): |
| 48 | body = json.dumps(data, ensure_ascii=False).encode() |
| 49 | self.send_response(status) |
| 50 | self.send_header("Content-Type", "application/json") |
| 51 | self.send_header("Access-Control-Allow-Origin", "*") |
| 52 | self.send_header("Content-Length", str(len(body))) |
| 53 | self.end_headers() |
| 54 | self.wfile.write(body) |
| 55 | |
| 56 | def _start_sse(self): |
| 57 | self.send_response(200) |
| 58 | self.send_header("Content-Type", "text/event-stream") |
| 59 | self.send_header("Cache-Control", "no-cache") |
| 60 | self.send_header("Access-Control-Allow-Origin", "*") |
| 61 | self.end_headers() |
| 62 | |
| 63 | def _parse_body(self, body: bytes) -> dict: |
| 64 | try: |
| 65 | return json.loads(body) |
| 66 | except (json.JSONDecodeError, ValueError): |
| 67 | return None |
| 68 | |
| 69 | def _authorized(self): |
| 70 | keys = CONFIG.get("api_keys") or [] |
| 71 | if not keys: |
| 72 | return True |
| 73 | auth = self.headers.get("Authorization", "") |
| 74 | key = auth[7:] if auth.startswith("Bearer ") else self.headers.get("x-api-key", "") |
| 75 | return key in keys |
| 76 | |
| 77 | def do_OPTIONS(self): |
| 78 | self.send_response(204) |
| 79 | self.send_header("Access-Control-Allow-Origin", "*") |
| 80 | self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") |
| 81 | self.send_header("Access-Control-Allow-Headers", "*") |
| 82 | self.end_headers() |
| 83 | |
| 84 | def do_GET(self): |
| 85 | try: |
| 86 | if self.path.startswith("/v1/") and not self._authorized(): |
| 87 | self.send_json({"error": {"message": "invalid api key"}}, 401) |
| 88 | return |
| 89 | if self.path == "/v1/models": |
| 90 | self.send_json({"object": "list", "data": [ |
| 91 | {"id": n, "object": "model", "created": 1700000000, |
| 92 | "owned_by": "google", "description": c["desc"]} |
| 93 | for n, c in MODELS.items() |
| 94 | ]}) |
| 95 | elif self.path.startswith("/v1beta/models"): |
| 96 | self.send_json({"models": [ |
| 97 | {"name": f"models/{n}", "displayName": n, "description": c["desc"], |
| 98 | "supportedGenerationMethods": ["generateContent", "streamGenerateContent"]} |
| 99 | for n, c in MODELS.items() |
| 100 | ]}) |
nothing calls this directly
no outgoing calls
no test coverage detected