Elysiadev11 commited on
Commit
7b8bec2
Β·
verified Β·
1 Parent(s): aa0cd44

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -31
app.py CHANGED
@@ -5,7 +5,7 @@ import httpx
5
  from typing import Dict
6
 
7
  from fastapi import FastAPI, Request, HTTPException
8
- from fastapi.responses import Response, StreamingResponse, JSONResponse
9
 
10
  app = FastAPI()
11
 
@@ -26,25 +26,23 @@ def load_keys(prefix="OLLAMA_KEY_"):
26
  return keys
27
 
28
  API_KEYS = load_keys()
29
- print(f"[INIT] Loaded {len(API_KEYS)} keys")
30
 
31
  # ─────────────────────────────
32
  # STATE
33
  # ─────────────────────────────
34
  key_status: Dict[str, Dict] = {
35
- k: {
36
- "fail": 0,
37
- "cooldown": 0,
38
- "status": "active"
39
- }
40
  for k in API_KEYS
41
  }
42
 
43
  # ─────────────────────────────
44
- # AUTH
45
  # ─────────────────────────────
46
  def auth(req: Request):
47
- if req.headers.get("Authorization") != f"Bearer {MASTER_API_KEY}":
 
 
48
  raise HTTPException(401, "Unauthorized")
49
 
50
  # ─────────────────────────────
@@ -89,16 +87,13 @@ async def proxy(req: Request, path: str):
89
  for _ in range(len(API_KEYS)):
90
  key = pick_key()
91
  if not key:
92
- return JSONResponse({"error": "all keys exhausted"}, 503)
93
 
94
  headers["Authorization"] = f"Bearer {key}"
95
 
96
  try:
97
  async with httpx.AsyncClient(timeout=60) as client:
98
-
99
- # ─────────────────────────────
100
- # STEP 1: VALIDATE REQUEST (NO STREAM)
101
- # ─────────────────────────────
102
  test = await client.request(
103
  method=req.method,
104
  url=target_url,
@@ -114,13 +109,18 @@ async def proxy(req: Request, path: str):
114
  key_status[key]["fail"] += 1
115
  if key_status[key]["fail"] >= 3:
116
  mark_dead(key)
117
- continue
 
 
 
 
 
 
 
118
 
119
  mark_ok(key)
120
 
121
- # ─────────────────────────────
122
- # STEP 2: STREAM RESPONSE (SAFE)
123
- # ─────────────────────────────
124
  stream = await client.stream(
125
  method=req.method,
126
  url=target_url,
@@ -131,26 +131,19 @@ async def proxy(req: Request, path: str):
131
 
132
  return StreamingResponse(
133
  stream.aiter_bytes(),
134
- media_type=test.headers.get(
135
- "content-type",
136
- "application/json"
137
- )
138
  )
139
 
140
  except Exception as e:
141
  key_status[key]["fail"] += 1
142
-
143
  if key_status[key]["fail"] >= 3:
144
  mark_dead(key)
145
-
146
- print(f"[ERROR] key={key[:6]} -> {e}")
147
 
148
  return JSONResponse(
149
- {
150
- "error": "all keys failed",
151
- "hint": "check keys / model access / BASE_URL"
152
- },
153
- 500
154
  )
155
 
156
  # ─────────────────────────────
@@ -158,8 +151,10 @@ async def proxy(req: Request, path: str):
158
  # ─────────────────────────────
159
  @app.get("/")
160
  def root():
 
161
  return {
162
  "status": "ok",
163
  "mode": "openai-proxy-fixed",
164
- "keys": len(API_KEYS)
 
165
  }
 
5
  from typing import Dict
6
 
7
  from fastapi import FastAPI, Request, HTTPException
8
+ from fastapi.responses import JSONResponse, StreamingResponse
9
 
10
  app = FastAPI()
11
 
 
26
  return keys
27
 
28
  API_KEYS = load_keys()
29
+ print(f"[INIT] Loaded {len(API_KEYS)} keys: {[k[:10] for k in API_KEYS}")
30
 
31
  # ─────────────────────────────
32
  # STATE
33
  # ─────────────────────────────
34
  key_status: Dict[str, Dict] = {
35
+ k: {"fail": 0, "cooldown": 0, "status": "active"}
 
 
 
 
36
  for k in API_KEYS
37
  }
38
 
39
  # ─────────────────────────────
40
+ # AUTH - Accept valid backend key OR master key
41
  # ─────────────────────────────
42
  def auth(req: Request):
43
+ auth_header = req.headers.get("Authorization", "").replace("Bearer ", "")
44
+ # Accept if: (1) it's a valid backend key OR (2) it's master key
45
+ if auth_header not in API_KEYS and auth_header != MASTER_API_KEY:
46
  raise HTTPException(401, "Unauthorized")
47
 
48
  # ─────────────────────────────
 
87
  for _ in range(len(API_KEYS)):
88
  key = pick_key()
89
  if not key:
90
+ return JSONResponse({"error": "all keys failed"}, status_code=503)
91
 
92
  headers["Authorization"] = f"Bearer {key}"
93
 
94
  try:
95
  async with httpx.AsyncClient(timeout=60) as client:
96
+ # Validate request first
 
 
 
97
  test = await client.request(
98
  method=req.method,
99
  url=target_url,
 
109
  key_status[key]["fail"] += 1
110
  if key_status[key]["fail"] >= 3:
111
  mark_dead(key)
112
+ continue
113
+
114
+ mark_ok(key)
115
+ return Response(
116
+ content=test.content,
117
+ status_code=test.status_code,
118
+ headers=dict(test.headers)
119
+ )
120
 
121
  mark_ok(key)
122
 
123
+ # Stream response
 
 
124
  stream = await client.stream(
125
  method=req.method,
126
  url=target_url,
 
131
 
132
  return StreamingResponse(
133
  stream.aiter_bytes(),
134
+ media_type=test.headers.get("content-type", "application/json")
 
 
 
135
  )
136
 
137
  except Exception as e:
138
  key_status[key]["fail"] += 1
 
139
  if key_status[key]["fail"] >= 3:
140
  mark_dead(key)
141
+ print(f"[ERROR] key={key[:10]} -> {e}")
142
+ continue
143
 
144
  return JSONResponse(
145
+ {"error": "all keys failed", "hint": "check keys / model access / BASE_URL"},
146
+ status_code=500
 
 
 
147
  )
148
 
149
  # ─────────────────────────────
 
151
  # ─────────────────────────────
152
  @app.get("/")
153
  def root():
154
+ active = sum(1 for v in key_status.values() if v["status"] == "active")
155
  return {
156
  "status": "ok",
157
  "mode": "openai-proxy-fixed",
158
+ "keys": len(API_KEYS),
159
+ "active": active
160
  }