proxycf / app.py
aaxaxax's picture
Force deploy
fdb04f0
raw
history blame
3.27 kB
import os
import time
import random
import httpx
from typing import Dict
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse, Response
app = FastAPI()
BASE_URL = os.getenv("BASE_URL", "https://ollama.com")
# CLIENT API KEY (for auth)
MASTER_API_KEY = "ollama-proxy-free"
# BACKEND API KEYS (for Ollama)
API_KEYS = [
"8ca25de51e554c099962b78b7ce0c9e9.Mp5dnqctR2zzq3g-NO_M-cjW",
"dbd1d0c534964684a6d4678348ab8d30.ieDfmSYVnf0MmTjR-AIdNrW9",
"37e81a6be4104fbfbfbe2ecf557a2c10.GoIbzpHebdM9ZcHarQ9A12Cp"
]
# KEY STATUS
key_status: Dict[str, Dict] = {
k: {"fail": 0, "cooldown": 0, "status": "active"}
for k in API_KEYS
}
def auth(req: Request):
"""Validate client API key"""
client_key = req.headers.get("Authorization", "").replace("Bearer ", "")
if client_key != MASTER_API_KEY:
raise HTTPException(401, "Unauthorized")
def pick_key():
now = time.time()
valid = [k for k, v in key_status.items()
if v["status"] != "dead" and v["cooldown"] < now]
if valid:
return random.choice(valid)
# Reset if all failed
for k in key_status:
key_status[k]["status"] = "active"
key_status[k]["fail"] = 0
return random.choice(API_KEYS)
def mark_fail(key: str):
key_status[key]["fail"] += 1
if key_status[key]["fail"] >= 3:
key_status[key]["cooldown"] = time.time() + 60
def mark_ok(key: str):
key_status[key]["fail"] = 0
key_status[key]["status"] = "active"
@app.get("/")
def root():
active = sum(1 for v in key_status.values() if v["status"] == "active")
return {
"status": "ok",
"mode": "openai-proxy",
"keys_total": len(API_KEYS),
"keys_active": active
}
@app.api_route("/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy(req: Request, path: str):
# Auth first
auth(req)
target_url = f"{BASE_URL}/v1/{path}"
body = await req.body()
headers = dict(req.headers)
headers.pop("host", None)
headers.pop("content-length", None)
# Try each key
tried = set()
for _ in range(len(API_KEYS)):
key = pick_key()
if key in tried:
continue
tried.add(key)
headers["Authorization"] = f"Bearer {key}"
try:
async with httpx.AsyncClient(timeout=60) as client:
resp = await client.request(
method=req.method,
url=target_url,
headers=headers,
content=body,
params=req.query_params
)
if resp.status_code < 400:
mark_ok(key)
return Response(
content=resp.content,
status_code=resp.status_code,
headers=dict(resp.headers)
)
mark_fail(key)
continue
except Exception as e:
mark_fail(key)
continue
return JSONResponse({"error": "all keys failed"}, status_code=500)
# rebuild
# Testing build