bobocup commited on
Commit
b336412
·
verified ·
1 Parent(s): 3b269c5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -39
app.py CHANGED
@@ -6,11 +6,14 @@ import json
6
  from typing import List, Optional
7
  import requests
8
  from itertools import cycle
 
9
 
10
- # 创建FastAPI应用,设置API前缀
11
- app = FastAPI(openapi_url="/api/openapi.json", docs_url="/api/docs")
 
 
 
12
 
13
- # CORS设置
14
  app.add_middleware(
15
  CORSMiddleware,
16
  allow_origins=["*"],
@@ -19,9 +22,8 @@ app.add_middleware(
19
  allow_headers=["*"],
20
  )
21
 
22
- # 配置
23
  class Config:
24
- OPENAI_API_BASE = "https://api.x.ai/v1"
25
  KEYS_URL = os.getenv("KEYS_URL", "")
26
  WHITELIST_IPS = os.getenv("WHITELIST_IPS", "").split(",")
27
 
@@ -29,7 +31,6 @@ class Config:
29
  keys = []
30
  key_cycle = None
31
 
32
- # 初始化keys
33
  def init_keys():
34
  global keys, key_cycle
35
  try:
@@ -41,13 +42,12 @@ def init_keys():
41
  keys = [k.strip() for k in f.readlines() if k.strip()]
42
 
43
  key_cycle = cycle(keys)
44
- print(f"Loaded {len(keys)} API keys")
45
  except Exception as e:
46
- print(f"Error loading keys: {e}")
47
  keys = []
48
  key_cycle = cycle(keys)
49
 
50
- # IP白名单中间件
51
  @app.middleware("http")
52
  async def ip_whitelist(request: Request, call_next):
53
  if Config.WHITELIST_IPS and Config.WHITELIST_IPS[0]:
@@ -56,43 +56,64 @@ async def ip_whitelist(request: Request, call_next):
56
  raise HTTPException(status_code=403, detail="IP not allowed")
57
  return await call_next(request)
58
 
59
- # 获取下一个key
60
  def get_next_key():
61
  if not keys:
62
  raise HTTPException(status_code=500, detail="No API keys available")
63
  return next(key_cycle)
64
 
65
- # 代理请求到X.AI,注意路径前缀改为/api
66
- @app.api_route("/api/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
67
  async def proxy(path: str, request: Request):
68
- # 获取请求体
69
- body = await request.body()
70
- # 获取查询参数
71
- params = dict(request.query_params)
72
- # 获取headers
73
- headers = dict(request.headers)
74
- headers.pop("host", None)
75
-
76
- # 设置API key
77
- headers["Authorization"] = f"Bearer {get_next_key()}"
78
-
79
- # 构建目标URL
80
- url = f"{Config.OPENAI_API_BASE}/{path}"
81
-
82
- async with httpx.AsyncClient() as client:
83
- try:
84
- response = await client.request(
85
- method=request.method,
86
- url=url,
87
- params=params,
88
- headers=headers,
89
- content=body
90
- )
91
- return response.json()
92
- except Exception as e:
93
- raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- # 启动时初始化
96
  @app.on_event("startup")
97
  async def startup_event():
98
  init_keys()
 
6
  from typing import List, Optional
7
  import requests
8
  from itertools import cycle
9
+ import logging
10
 
11
+ # 设置日志
12
+ logging.basicConfig(level=logging.INFO)
13
+ logger = logging.getLogger(__name__)
14
+
15
+ app = FastAPI(openapi_url="/api/v1/openapi.json", docs_url="/api/v1/docs")
16
 
 
17
  app.add_middleware(
18
  CORSMiddleware,
19
  allow_origins=["*"],
 
22
  allow_headers=["*"],
23
  )
24
 
 
25
  class Config:
26
+ OPENAI_API_BASE = "https://api.x.ai" # 移除 /v1
27
  KEYS_URL = os.getenv("KEYS_URL", "")
28
  WHITELIST_IPS = os.getenv("WHITELIST_IPS", "").split(",")
29
 
 
31
  keys = []
32
  key_cycle = None
33
 
 
34
  def init_keys():
35
  global keys, key_cycle
36
  try:
 
42
  keys = [k.strip() for k in f.readlines() if k.strip()]
43
 
44
  key_cycle = cycle(keys)
45
+ logger.info(f"Loaded {len(keys)} API keys")
46
  except Exception as e:
47
+ logger.error(f"Error loading keys: {e}")
48
  keys = []
49
  key_cycle = cycle(keys)
50
 
 
51
  @app.middleware("http")
52
  async def ip_whitelist(request: Request, call_next):
53
  if Config.WHITELIST_IPS and Config.WHITELIST_IPS[0]:
 
56
  raise HTTPException(status_code=403, detail="IP not allowed")
57
  return await call_next(request)
58
 
 
59
  def get_next_key():
60
  if not keys:
61
  raise HTTPException(status_code=500, detail="No API keys available")
62
  return next(key_cycle)
63
 
64
+ @app.api_route("/api/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
 
65
  async def proxy(path: str, request: Request):
66
+ try:
67
+ # 获取请求信息
68
+ body = await request.body()
69
+ params = dict(request.query_params)
70
+ headers = dict(request.headers)
71
+ headers.pop("host", None)
72
+
73
+ # 设置API key
74
+ api_key = get_next_key()
75
+ headers["Authorization"] = f"Bearer {api_key}"
76
+
77
+ # 构建目标URL
78
+ url = f"{Config.OPENAI_API_BASE}/v1/{path}"
79
+
80
+ logger.info(f"Proxying request to: {url}")
81
+ logger.info(f"Method: {request.method}")
82
+ logger.info(f"Headers: {headers}")
83
+
84
+ async with httpx.AsyncClient() as client:
85
+ try:
86
+ response = await client.request(
87
+ method=request.method,
88
+ url=url,
89
+ params=params,
90
+ headers=headers,
91
+ content=body,
92
+ timeout=30.0 # 增加超时时间
93
+ )
94
+
95
+ # 记录响应状态
96
+ logger.info(f"Response status: {response.status_code}")
97
+
98
+ # 如果响应不是200,记录错误信息
99
+ if response.status_code != 200:
100
+ logger.error(f"Error response: {response.text}")
101
+
102
+ return response.json()
103
+ except httpx.HTTPError as e:
104
+ logger.error(f"HTTP error occurred: {e}")
105
+ raise HTTPException(status_code=500, detail=str(e))
106
+ except Exception as e:
107
+ logger.error(f"Unexpected error: {e}")
108
+ raise HTTPException(status_code=500, detail=str(e))
109
+ except Exception as e:
110
+ logger.error(f"Error in proxy function: {e}")
111
+ raise HTTPException(status_code=500, detail=str(e))
112
+
113
+ @app.get("/api/v1/health")
114
+ async def health_check():
115
+ return {"status": "healthy", "key_count": len(keys)}
116
 
 
117
  @app.on_event("startup")
118
  async def startup_event():
119
  init_keys()