aaxaxax commited on
Commit
5904245
·
1 Parent(s): c90617f

Minimal proxy test

Browse files
Files changed (1) hide show
  1. app.py +33 -104
app.py CHANGED
@@ -1,119 +1,48 @@
1
  import os
2
- import time
3
- import random
4
  import httpx
5
- from typing import Dict
6
-
7
- from fastapi import FastAPI, Request, HTTPException
8
  from fastapi.responses import JSONResponse, StreamingResponse, Response
9
 
10
  app = FastAPI()
11
 
12
- # CONFIG
13
- MASTER_API_KEY = os.getenv("MASTER_API_KEY", "changeme")
14
  BASE_URL = os.getenv("BASE_URL", "https://ollama.com")
15
 
16
- # LOAD KEYS - HARDCODED FOR TESTING
17
- def load_keys(prefix="OLLAMA_KEY_"):
18
- # Hardcoded keys - please update!
19
- return [
20
- "8ca25de51e554c099962b78b7ce0c9e9.Mp5dnqctR2zzq3g-NO_M-cjW",
21
- "dbd1d0c534964684a6d4678348ab8d30.ieDfmSYVnf0MmTjR-AIdNrW9",
22
- "37e81a6be4104fbfbfbe2ecf557a2c10.GoIbzpHebdM9ZcHarQ9A12Cp"
23
- ]
24
-
25
- API_KEYS = load_keys()
26
- print(f"[INIT] Keys: {len(API_KEYS)}")
27
-
28
- key_status = {k: {"fail": 0, "cooldown": 0, "status": "active"} for k in API_KEYS}
29
-
30
- # AUTH - ACCEPT ALL
31
- def auth(req: Request):
32
- return
33
-
34
- def pick_key():
35
- now = time.time()
36
- valid = [k for k, v in key_status.items() if v["status"] != "dead" and v["cooldown"] < now]
37
- return random.choice(valid) if valid else None
38
-
39
- def mark_limit(k):
40
- key_status[k]["cooldown"] = time.time() + 60
41
- key_status[k]["status"] = "limited"
42
-
43
- def mark_dead(k):
44
- key_status[k]["status"] = "dead"
45
-
46
- def mark_ok(k):
47
- key_status[k]["fail"] = 0
48
- key_status[k]["status"] = "active"
49
 
50
- @app.api_route("/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
51
  async def proxy(req: Request, path: str):
52
- print(f"[PROXY] path={path}, auth done")
53
- auth(req)
54
-
55
  target_url = f"{BASE_URL}/v1/{path}"
56
  body = await req.body()
57
-
58
  headers = dict(req.headers)
59
  headers.pop("host", None)
60
  headers.pop("content-length", None)
61
-
62
- for _ in range(len(API_KEYS)):
63
- key = pick_key()
64
- if not key:
65
- return JSONResponse({"error": "all keys failed"}, status_code=503)
66
-
67
- headers["Authorization"] = f"Bearer {key}"
68
- print(f"[PROXY] key={key[:6]}.. url={target_url}")
69
-
70
- try:
71
- async with httpx.AsyncClient(timeout=60) as client:
72
- test = await client.request(
73
- method=req.method,
74
- url=target_url,
75
- headers=headers,
76
- content=body,
77
- params=req.query_params
78
- )
79
-
80
- if test.status_code >= 400:
81
- if test.status_code == 429:
82
- mark_limit(key)
83
- elif test.status_code >= 500:
84
- key_status[key]["fail"] += 1
85
- if key_status[key]["fail"] >= 3:
86
- mark_dead(key)
87
- continue
88
- mark_ok(key)
89
- return Response(content=test.content, status_code=test.status_code, headers=dict(test.headers))
90
-
91
- mark_ok(key)
92
-
93
- stream = await client.stream(
94
- method=req.method,
95
- url=target_url,
96
- headers=headers,
97
- content=body,
98
- params=req.query_params
99
- )
100
-
101
- return StreamingResponse(
102
- stream.aiter_bytes(),
103
- media_type=test.headers.get("content-type", "application/json")
104
- )
105
-
106
- except Exception as e:
107
- key_status[key]["fail"] += 1
108
- if key_status[key]["fail"] >= 3:
109
- mark_dead(key)
110
- print(f"[ERROR] {type(e).__name__}: {e}")
111
- continue
112
-
113
- return JSONResponse({"error": "all keys failed"}, status_code=500)
114
-
115
- @app.get("/")
116
- def root():
117
- return {"status": "ok", "keys": len(API_KEYS)}
118
-
119
- # Rebuild test
 
1
  import os
 
 
2
  import httpx
3
+ from fastapi import FastAPI, Request
 
 
4
  from fastapi.responses import JSONResponse, StreamingResponse, Response
5
 
6
  app = FastAPI()
7
 
 
 
8
  BASE_URL = os.getenv("BASE_URL", "https://ollama.com")
9
 
10
+ @app.get("/")
11
+ def root():
12
+ return {"status": "ok", "base_url": BASE_URL}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ @app.api_route("/v1/{path:path}", methods=["GET", "POST"])
15
  async def proxy(req: Request, path: str):
16
+ print(f"[PROXY] request to {path}")
17
+
 
18
  target_url = f"{BASE_URL}/v1/{path}"
19
  body = await req.body()
20
+
21
  headers = dict(req.headers)
22
  headers.pop("host", None)
23
  headers.pop("content-length", None)
24
+
25
+ # Hardcoded key
26
+ headers["Authorization"] = "Bearer 37e81a6be4104fbfbfbe2ecf557a2c10.GoIbzpHebdM9ZcHarQ9A12Cp"
27
+
28
+ print(f"[PROXY] calling {target_url}")
29
+
30
+ try:
31
+ async with httpx.AsyncClient(timeout=60) as client:
32
+ resp = await client.request(
33
+ method=req.method,
34
+ url=target_url,
35
+ headers=headers,
36
+ content=body,
37
+ params=req.query_params
38
+ )
39
+ print(f"[PROXY] got {resp.status_code}")
40
+
41
+ return Response(
42
+ content=resp.content,
43
+ status_code=resp.status_code,
44
+ headers=dict(resp.headers)
45
+ )
46
+ except Exception as e:
47
+ print(f"[ERROR] {e}")
48
+ return JSONResponse({"error": str(e)}, status_code=500)