bobocup commited on
Commit
ddd6667
·
verified ·
1 Parent(s): c298b8e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -4
app.py CHANGED
@@ -1,6 +1,7 @@
1
  from fastapi import FastAPI, HTTPException, Request, Response
2
  from fastapi.middleware.cors import CORSMiddleware
3
- from fastapi.responses import StreamingResponse
 
4
  import httpx
5
  import os
6
  import json
@@ -27,7 +28,8 @@ class Config:
27
  OPENAI_API_BASE = "https://api.x.ai/v1"
28
  KEYS_URL = os.getenv("KEYS_URL", "")
29
  WHITELIST_IPS = os.getenv("WHITELIST_IPS", "").split(",")
30
- CHUNK_SIZE = 1 # 控制流式传输的块大小
 
31
 
32
  # 全局变量
33
  keys = []
@@ -53,7 +55,6 @@ def init_keys():
53
 
54
  # 获取真实IP地址
55
  def get_client_ip(request: Request) -> str:
56
- # 尝试从各种头部获取IP
57
  forwarded_for = request.headers.get("x-forwarded-for")
58
  if forwarded_for:
59
  return forwarded_for.split(",")[0].strip()
@@ -84,6 +85,92 @@ def get_next_key():
84
  raise HTTPException(status_code=500, detail="No API keys available")
85
  return next(key_cycle)
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  # 模型列表路由
88
  @app.get("/api/v1/models")
89
  async def list_models():
@@ -209,7 +296,7 @@ async def proxy(path: str, request: Request):
209
  # 获取并处理headers
210
  headers = dict(request.headers)
211
  headers.pop("host", None)
212
- headers["Authorization"] = f"Bearer {get_next_key()}"
213
  headers["Content-Type"] = "application/json"
214
 
215
  # 构建目标URL
 
1
  from fastapi import FastAPI, HTTPException, Request, Response
2
  from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.responses import StreamingResponse, HTMLResponse
4
+ from fastapi.staticfiles import StaticFiles
5
  import httpx
6
  import os
7
  import json
 
28
  OPENAI_API_BASE = "https://api.x.ai/v1"
29
  KEYS_URL = os.getenv("KEYS_URL", "")
30
  WHITELIST_IPS = os.getenv("WHITELIST_IPS", "").split(",")
31
+ ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "")
32
+ CHUNK_SIZE = 1
33
 
34
  # 全局变量
35
  keys = []
 
55
 
56
  # 获取真实IP地址
57
  def get_client_ip(request: Request) -> str:
 
58
  forwarded_for = request.headers.get("x-forwarded-for")
59
  if forwarded_for:
60
  return forwarded_for.split(",")[0].strip()
 
85
  raise HTTPException(status_code=500, detail="No API keys available")
86
  return next(key_cycle)
87
 
88
+ # 添加静态文件支持
89
+ app.mount("/static", StaticFiles(directory="static"), name="static")
90
+
91
+ # 管理页面路由
92
+ @app.get("/admin", response_class=HTMLResponse)
93
+ async def admin_page():
94
+ try:
95
+ with open("static/admin.html", "r", encoding="utf-8") as f:
96
+ return f.read()
97
+ except Exception as e:
98
+ print(f"Error loading admin page: {e}")
99
+ raise HTTPException(status_code=500, detail="Error loading admin page")
100
+
101
+ # 验证管理密码
102
+ @app.post("/api/admin/login")
103
+ async def admin_login(password: str):
104
+ if password == Config.ADMIN_PASSWORD:
105
+ return {"status": "success"}
106
+ raise HTTPException(status_code=401, detail="Invalid password")
107
+
108
+ # 获取所有keys(需要密码)
109
+ @app.get("/api/keys")
110
+ async def get_keys(password: str):
111
+ if password != Config.ADMIN_PASSWORD:
112
+ raise HTTPException(status_code=401, detail="Invalid password")
113
+ return {"keys": list(keys)}
114
+
115
+ # 检查key是否有效
116
+ async def check_key_valid(key: str) -> bool:
117
+ headers = {
118
+ "Authorization": f"Bearer {key}",
119
+ "Content-Type": "application/json"
120
+ }
121
+
122
+ async with httpx.AsyncClient() as client:
123
+ try:
124
+ response = await client.get(
125
+ f"{Config.OPENAI_API_BASE}/models",
126
+ headers=headers
127
+ )
128
+ return response.status_code == 200
129
+ except:
130
+ return False
131
+
132
+ # 添加新key(需要密码)
133
+ @app.post("/api/keys")
134
+ async def add_key(key: str, password: str):
135
+ if password != Config.ADMIN_PASSWORD:
136
+ raise HTTPException(status_code=401, detail="Invalid password")
137
+
138
+ if key not in keys:
139
+ # 检查key是否有效
140
+ is_valid = await check_key_valid(key)
141
+ if not is_valid:
142
+ raise HTTPException(status_code=400, detail="Invalid key")
143
+
144
+ keys.append(key)
145
+ global key_cycle
146
+ key_cycle = cycle(keys)
147
+ return {"status": "success", "message": "Key added successfully"}
148
+
149
+ raise HTTPException(status_code=400, detail="Key already exists")
150
+
151
+ # 删除key(需要密码)
152
+ @app.delete("/api/keys/{key}")
153
+ async def delete_key(key: str, password: str):
154
+ if password != Config.ADMIN_PASSWORD:
155
+ raise HTTPException(status_code=401, detail="Invalid password")
156
+
157
+ if key in keys:
158
+ keys.remove(key)
159
+ global key_cycle
160
+ key_cycle = cycle(keys)
161
+ return {"status": "success", "message": "Key deleted successfully"}
162
+
163
+ raise HTTPException(status_code=404, detail="Key not found")
164
+
165
+ # 检查key状态(需要密码)
166
+ @app.get("/api/keys/check/{key}")
167
+ async def check_key(key: str, password: str):
168
+ if password != Config.ADMIN_PASSWORD:
169
+ raise HTTPException(status_code=401, detail="Invalid password")
170
+
171
+ is_valid = await check_key_valid(key)
172
+ return {"valid": is_valid}
173
+
174
  # 模型列表路由
175
  @app.get("/api/v1/models")
176
  async def list_models():
 
296
  # 获取并处理headers
297
  headers = dict(request.headers)
298
  headers.pop("host", None)
299
+ headers["Authorization"] = f"Bearer {get_next_key()}",
300
  headers["Content-Type"] = "application/json"
301
 
302
  # 构建目标URL