aaxaxax commited on
Commit
6ef5c36
·
1 Parent(s): fdb04f0

Add more debug

Browse files
Files changed (1) hide show
  1. app.py +40 -57
app.py CHANGED
@@ -9,95 +9,81 @@ from fastapi.responses import JSONResponse, StreamingResponse, Response
9
  app = FastAPI()
10
 
11
  BASE_URL = os.getenv("BASE_URL", "https://ollama.com")
12
-
13
- # CLIENT API KEY (for auth)
14
  MASTER_API_KEY = "ollama-proxy-free"
15
 
16
- # BACKEND API KEYS (for Ollama)
17
  API_KEYS = [
18
  "8ca25de51e554c099962b78b7ce0c9e9.Mp5dnqctR2zzq3g-NO_M-cjW",
19
  "dbd1d0c534964684a6d4678348ab8d30.ieDfmSYVnf0MmTjR-AIdNrW9",
20
  "37e81a6be4104fbfbfbe2ecf557a2c10.GoIbzpHebdM9ZcHarQ9A12Cp"
21
  ]
22
 
23
- # KEY STATUS
24
- key_status: Dict[str, Dict] = {
25
- k: {"fail": 0, "cooldown": 0, "status": "active"}
26
- for k in API_KEYS
27
- }
28
 
29
  def auth(req: Request):
30
- """Validate client API key"""
31
- client_key = req.headers.get("Authorization", "").replace("Bearer ", "")
32
- if client_key != MASTER_API_KEY:
33
  raise HTTPException(401, "Unauthorized")
 
34
 
35
- def pick_key():
36
  now = time.time()
37
- valid = [k for k, v in key_status.items()
38
- if v["status"] != "dead" and v["cooldown"] < now]
39
-
40
- if valid:
41
- return random.choice(valid)
42
-
43
- # Reset if all failed
44
- for k in key_status:
45
- key_status[k]["status"] = "active"
46
- key_status[k]["fail"] = 0
47
-
48
- return random.choice(API_KEYS)
49
 
50
- def mark_fail(key: str):
51
- key_status[key]["fail"] += 1
52
- if key_status[key]["fail"] >= 3:
53
- key_status[key]["cooldown"] = time.time() + 60
54
 
55
- def mark_ok(key: str):
56
- key_status[key]["fail"] = 0
57
- key_status[key]["status"] = "active"
58
 
59
  @app.get("/")
60
  def root():
61
- active = sum(1 for v in key_status.values() if v["status"] == "active")
62
- return {
63
- "status": "ok",
64
- "mode": "openai-proxy",
65
- "keys_total": len(API_KEYS),
66
- "keys_active": active
67
- }
 
68
 
69
  @app.api_route("/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
70
  async def proxy(req: Request, path: str):
71
- # Auth first
72
- auth(req)
 
 
73
 
74
- target_url = f"{BASE_URL}/v1/{path}"
75
  body = await req.body()
76
-
77
  headers = dict(req.headers)
78
  headers.pop("host", None)
79
  headers.pop("content-length", None)
 
 
80
 
81
- # Try each key
82
- tried = set()
83
- for _ in range(len(API_KEYS)):
84
  key = pick_key()
85
- if key in tried:
86
- continue
87
- tried.add(key)
88
-
89
  headers["Authorization"] = f"Bearer {key}"
90
 
 
 
91
  try:
92
- async with httpx.AsyncClient(timeout=60) as client:
93
  resp = await client.request(
94
  method=req.method,
95
- url=target_url,
96
  headers=headers,
97
  content=body,
98
  params=req.query_params
99
  )
100
 
 
 
101
  if resp.status_code < 400:
102
  mark_ok(key)
103
  return Response(
@@ -107,12 +93,9 @@ async def proxy(req: Request, path: str):
107
  )
108
 
109
  mark_fail(key)
110
- continue
111
-
112
  except Exception as e:
 
113
  mark_fail(key)
114
- continue
115
-
116
  return JSONResponse({"error": "all keys failed"}, status_code=500)
117
- # rebuild
118
- # Testing build
 
9
  app = FastAPI()
10
 
11
  BASE_URL = os.getenv("BASE_URL", "https://ollama.com")
 
 
12
  MASTER_API_KEY = "ollama-proxy-free"
13
 
 
14
  API_KEYS = [
15
  "8ca25de51e554c099962b78b7ce0c9e9.Mp5dnqctR2zzq3g-NO_M-cjW",
16
  "dbd1d0c534964684a6d4678348ab8d30.ieDfmSYVnf0MmTjR-AIdNrW9",
17
  "37e81a6be4104fbfbfbe2ecf557a2c10.GoIbzpHebdM9ZcHarQ9A12Cp"
18
  ]
19
 
20
+ key_status = {k: {"fail": 0, "cooldown": 0, "status": "active"} for k in API_KEYS}
 
 
 
 
21
 
22
  def auth(req: Request):
23
+ key = req.headers.get("Authorization", "").replace("Bearer ", "")
24
+ if key != MASTER_API_KEY:
25
+ print(f"[AUTH] reject: {key[:8]} != {MASTER_API_KEY[:8]}")
26
  raise HTTPException(401, "Unauthorized")
27
+ print(f"[AUTH] ok")
28
 
29
+ def pick_key() -> str:
30
  now = time.time()
31
+ valid = [k for k, v in key_status.items() if v["status"] != "dead" and v["cooldown"] < now]
32
+ return random.choice(valid) if valid else random.choice(API_KEYS)
 
 
 
 
 
 
 
 
 
 
33
 
34
+ def mark_fail(k):
35
+ key_status[k]["fail"] += 1
36
+ if key_status[k]["fail"] >= 3:
37
+ key_status[k]["cooldown"] = time.time() + 60
38
 
39
+ def mark_ok(k):
40
+ key_status[k]["fail"] = 0
41
+ key_status[k]["status"] = "active"
42
 
43
  @app.get("/")
44
  def root():
45
+ return {"status": "ok", "keys": len(API_KEYS), "master_set": MASTER_API_KEY[:10]}
46
+
47
+ # Simple route for testing
48
+ @app.post("/test")
49
+ def test(req: Request):
50
+ auth(req)
51
+ key = pick_key()
52
+ return {"key": key[:10], "url": BASE_URL}
53
 
54
  @app.api_route("/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
55
  async def proxy(req: Request, path: str):
56
+ try:
57
+ auth(req)
58
+ except HTTPException:
59
+ raise
60
 
61
+ target = f"{BASE_URL}/v1/{path}"
62
  body = await req.body()
 
63
  headers = dict(req.headers)
64
  headers.pop("host", None)
65
  headers.pop("content-length", None)
66
+
67
+ print(f"[PROXY] {req.method} {path}")
68
 
69
+ for i in range(len(API_KEYS)):
 
 
70
  key = pick_key()
 
 
 
 
71
  headers["Authorization"] = f"Bearer {key}"
72
 
73
+ print(f"[TRY] key={key[:6]}...")
74
+
75
  try:
76
+ async with httpx.AsyncClient(timeout=120.0, follow_redirects=True) as client:
77
  resp = await client.request(
78
  method=req.method,
79
+ url=target,
80
  headers=headers,
81
  content=body,
82
  params=req.query_params
83
  )
84
 
85
+ print(f"[RESP] {key[:6]} <- {resp.status_code}")
86
+
87
  if resp.status_code < 400:
88
  mark_ok(key)
89
  return Response(
 
93
  )
94
 
95
  mark_fail(key)
 
 
96
  except Exception as e:
97
+ print(f"[ERR] {key[:6]} {type(e).__name__}: {e}")
98
  mark_fail(key)
99
+
100
+ print("[FAIL] all keys failed")
101
  return JSONResponse({"error": "all keys failed"}, status_code=500)