tanbushi commited on
Commit
b4872ed
·
1 Parent(s): 3375e89
Files changed (1) hide show
  1. app.py +64 -84
app.py CHANGED
@@ -4,14 +4,14 @@ from fastapi import FastAPI, Request, HTTPException, Depends, status
4
  from fastapi.responses import Response # 导入Response
5
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials # 导入HTTPBearer和HTTPAuthorizationCredentials
6
  import httpx # 使用httpx替代requests,因为requests是同步的,而FastAPI是异步的
7
- import os, json
8
  from dotenv import load_dotenv
9
  from enum import Enum
10
  from supabase import create_client, Client
 
11
 
12
  # 加载环境变量
13
  load_dotenv()
14
- print('000000000000-111111111-222222')
15
 
16
  # 从环境变量获取代理自身的API密钥
17
  proxy_api_key = os.getenv("PROXY_API_KEY")
@@ -55,102 +55,82 @@ async def health_check():
55
  @app.api_route("/v1/{protocol}/{host}/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
56
  # @app.api_route("/v1/{protocol}/{host}/{path:path}", methods=["POST"])
57
  async def proxy(request: Request, protocol: ProtocolType, host:str, path: str, proxy_api_key: str = Depends(verify_proxy_api_key)): # 添加代理认证依赖
58
-
59
- print('\n\n======================================')
60
-
61
- real_url = f"{protocol.value}://{host}/{path}"
62
-
63
- # 提取客户端请求的headers和body,透传给Gemini
64
- client_headers = dict(request.headers)
65
-
66
- # 移除FastAPI自带的Host头,避免Gemini校验报错
67
- client_headers.pop("host", None)
68
- client_headers.pop("authorization", None)
69
- client_headers.pop("user-agent", None)
70
- client_headers.pop("content-length", None)
71
-
72
- # 将User-Agent改为curl/8.7.1,以模拟curl请求
73
- client_headers["User-Agent"] = "curl/8.7.1"
74
 
75
  try:
76
- # 读取客户端请求体
77
- client_body = await request.body()
78
- # print('client_body', client_body)
79
-
80
- # 尝试从请求体中获取model
81
- model_from_body = None
82
- try:
83
- if client_body:
84
- body_json = json.loads(client_body)
85
- # print('body_json', body_json)
86
- model_from_body = body_json.get("model")
87
- # print('model_from_body', model_from_body)
88
- except json.JSONDecodeError:
89
- # 如果请求体不是JSON,则忽略
90
- pass
91
-
92
- print('model', model_from_body)
93
-
94
- # 获取 api_key
95
- api_key = await get_api_key(model_from_body if model_from_body else 'glm-4-flash')
96
- api_key_show = api_key[:5] + '...' + api_key[-5:]
97
- print('api_key', api_key_show)
98
- if not api_key:
99
- raise HTTPException(status_code=500, detail="没有可用的API密钥!")
100
-
101
- # 使用httpx异步客户端发起请求
102
- async with httpx.AsyncClient() as client:
103
- client_headers["Authorization"] = f"Bearer {api_key}"
104
- response = await client.request(
105
- method=request.method,
106
- url=real_url,
107
- headers=client_headers,
108
- content=client_body, # httpx使用content参数传递请求体
109
- timeout=30 # 超时时间,可调整
110
- )
111
-
112
- # 将Gemini的响应透传给客户端
113
- return Response(
114
- content=response.content,
115
- status_code=response.status_code,
116
- headers=dict(response.headers)
117
- )
118
-
119
- except httpx.RequestError as e:
120
- print('\n\n----------------- 1 ------------------')
121
- print(str(e))
122
- print('\n\n----------------- 2 ------------------')
123
- # return
124
- # raise HTTPException(status_code=e.response.status_code, detail=f"转发请求失败:{str(e)}")
125
- raise HTTPException(status_code=500, detail=f"转发请求失败:{str(e)}")
126
- except httpx.HTTPStatusError as e:
127
- print('\n\n----------------- 3 ------------------')
128
- print(str(e))
129
- print('\n\n----------------- 4 ------------------')
130
- raise HTTPException(status_code=e.response.status_code, detail=f"目标API返回错误:{e.response.text}")
131
  except Exception as e:
132
- print('\n\n----------------- 5 ------------------')
133
- print(str(e))
134
- print('\n\n----------------- 6 ------------------')
135
- # raise HTTPException(status_code=e.response.status_code, detail=f"转发失败:{str(e)}")
136
- raise HTTPException(status_code=500, detail=f"转发失败:{str(e)}")
 
 
137
 
138
- async def get_api_key(model: str = None):
139
  try:
140
  # 根据用户提供的SQL语句修改,从 'airs_model_api_keys_view' 视图中获取 'api_key'
141
  if model:
142
- response = supabase.from_('airs_model_api_keys_view').select('api_key').eq('model_name', model).order('api_key_ran_at', desc=False).limit(1).execute()
143
- # print(response.data)
144
  else:
145
  # 如果没有提供model,则获取所有模型的api_key
146
  raise HTTPException(status_code=400, detail="请提供模型名称!")
147
- # response = supabase.from_('airs_model_api_keys_view').select('api_key').order('api_key_ran_at', desc=False).limit(1).execute()
148
 
149
  if response.data:
150
- # 由于已经limit(1),直接返回第一条记录
151
- return response.data[0]['api_key']
152
  else:
153
  return None
154
  except Exception as e:
155
  print(f"从Supabase获取API密钥失败: {e}")
156
  return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from fastapi.responses import Response # 导入Response
5
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials # 导入HTTPBearer和HTTPAuthorizationCredentials
6
  import httpx # 使用httpx替代requests,因为requests是同步的,而FastAPI是异步的
7
+ import os, json, pprint
8
  from dotenv import load_dotenv
9
  from enum import Enum
10
  from supabase import create_client, Client
11
+ from datetime import datetime, timezone, time # 导入 datetime 和 timezone
12
 
13
  # 加载环境变量
14
  load_dotenv()
 
15
 
16
  # 从环境变量获取代理自身的API密钥
17
  proxy_api_key = os.getenv("PROXY_API_KEY")
 
55
  @app.api_route("/v1/{protocol}/{host}/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
56
  # @app.api_route("/v1/{protocol}/{host}/{path:path}", methods=["POST"])
57
  async def proxy(request: Request, protocol: ProtocolType, host:str, path: str, proxy_api_key: str = Depends(verify_proxy_api_key)): # 添加代理认证依赖
58
+ send_req = await make_send_req(request, protocol, host, path)
59
+
60
+ # 使用httpx异步客户端发起请求
61
+ async with httpx.AsyncClient() as client:
62
+ response = await client.request(
63
+ method=send_req.get('method'),
64
+ url=send_req.get('url'),
65
+ headers=send_req.get('headers'),
66
+ content=send_req.get('content'), # httpx使用content参数传递请求体
67
+ timeout=30 # 超时时间,可调整
68
+ )
 
 
 
 
 
69
 
70
  try:
71
+ current_local_time = datetime.now().isoformat()
72
+ supabase.table("airs_api_keys").update({"ran_at": current_local_time}).eq("id", send_req.get('api_key_info').get('api_key_id')).execute()
73
+ print('更新成功')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  except Exception as e:
75
+ raise HTTPException(status_code=500, detail="更新API密钥运行时间失败!")
76
+
77
+ return Response(
78
+ content=response.content,
79
+ status_code=response.status_code,
80
+ headers=dict(response.headers)
81
+ )
82
 
83
+ async def get_api_key_info(model: str = None):
84
  try:
85
  # 根据用户提供的SQL语句修改,从 'airs_model_api_keys_view' 视图中获取 'api_key'
86
  if model:
87
+ response = supabase.from_('airs_model_api_keys_view').select('api_key', 'api_key_id').eq('model_name', model).order('api_key_ran_at', desc=False).limit(1).execute()
 
88
  else:
89
  # 如果没有提供model,则获取所有模型的api_key
90
  raise HTTPException(status_code=400, detail="请提供模型名称!")
 
91
 
92
  if response.data:
93
+ api_key_info = response.data[0]
94
+ return api_key_info
95
  else:
96
  return None
97
  except Exception as e:
98
  print(f"从Supabase获取API密钥失败: {e}")
99
  return None
100
+
101
+ async def make_send_req(request: Request, protocol: ProtocolType, host:str, path: str):
102
+ _method = request.method
103
+ _url = f"{protocol.value}://{host}/{path}"
104
+ _headers = dict(request.headers)
105
+ # 移除FastAPI自带的Host头,避免Gemini校验报错
106
+ _headers.pop("host", None)
107
+ _headers.pop("authorization", None)
108
+ _headers.pop("user-agent", None)
109
+ _headers.pop("content-length", None)
110
+ # 将User-Agent改为curl/8.7.1,以模拟curl请求
111
+ _headers["User-Agent"] = "curl/8.7.1"
112
+
113
+ try:
114
+ # 读取客户端请求体
115
+ _content = await request.body()
116
+ content_json = json.loads(_content)
117
+ try:
118
+ _model = content_json.get("model")
119
+ except Exception as e:
120
+ print(f"获取模型名称失败: {e}")
121
+ return None
122
+ except Exception as e:
123
+ print(f"读取客户端请求体失败: {e}")
124
+ return None
125
+ _api_key_info = await get_api_key_info(_model)
126
+ _headers["Authorization"] = f"Bearer {_api_key_info['api_key']}"
127
+
128
+ send_req={
129
+ "method": _method,
130
+ "url": _url,
131
+ "headers": _headers,
132
+ "content": _content,
133
+ "model": _model,
134
+ "api_key_info": _api_key_info
135
+ }
136
+ return send_req