superproxy-all / articles /fastapi-gemini-proxy-tutorial.md
geqintan's picture
update
6a5b28d
# 使用 FastAPI 搭建 Gemini API 转发代理教程
## 1. 项目简介
本项目旨在搭建一个基于 FastAPI 的通用 API 转发代理,主要用于转发对 Google Gemini API(特别是其 OpenAI 兼容 API)的请求。通过此代理,您可以解决直接访问 Gemini API 可能遇到的地域限制、集中管理 API 密钥以及处理客户端请求头兼容性等问题。
## 2. 核心功能
* **代理认证**:代理自身支持 API 密钥认证,确保只有授权客户端才能使用代理服务。
* **请求转发**:接收来自客户端的 HTTP 请求(GET, POST, PUT, DELETE),并将其转发到预配置的目标 API。
* **请求/响应处理**:处理请求头、查询参数和请求体,并将目标 API 的响应原封不动地返回给客户端。
* **环境变量配置**:支持通过 `.env` 文件配置代理自身的认证密钥 (`PROXY_API_KEY`)、目标 API 的基 URL (`GEMINI_BASE_URL`) 和认证信息 (`GEMINI_API_KEY`)。
* **健康检查**:提供一个简单的 `/health` 端点,用于验证代理服务是否正常运行。
* **User-Agent 修改**:强制将转发请求的 `User-Agent` 头设置为 `curl/8.7.1`,以解决某些客户端(如 Postman)可能遇到的兼容性问题。
## 3. 技术栈
* **Python 3.9+**
* **FastAPI**:高性能 Python Web 框架。
* **Uvicorn**:ASGI 服务器。
* **httpx**:异步 HTTP 客户端。
* **python-dotenv**:环境变量管理。
## 4. 环境搭建与部署
### 4.1. 创建虚拟环境并安装依赖
建议使用 `conda``venv` 创建独立的 Python 虚拟环境:
```bash
conda create -n airs python=3.9
conda activate airs
```
在项目根目录创建 `requirements.txt` 文件,并添加以下内容:
```
fastapi
uvicorn[standard]
httpx
python-dotenv
```
然后安装依赖:
```bash
pip install -r requirements.txt
```
### 4.2. 配置环境变量
在项目根目录创建 `.env` 文件,并配置代理自身的 API 密钥、Gemini API 密钥和 OpenAI 兼容 API 的 Base URL:
```dotenv
PROXY_API_KEY="YOUR_PROXY_API_KEY"
GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
GEMINI_BASE_URL="https://generativelanguage.googleapis.com/v1beta/openai"
```
请将 `YOUR_PROXY_API_KEY` 替换为您为代理设置的密钥,将 `YOUR_GEMINI_API_KEY` 替换为您的实际 Gemini API 密钥。
### 4.3. `app.py` 代码实现
创建 `app.py` 文件,并添加以下代码:
```python
# uvicorn app:app --host 0.0.0.0 --port 7860 --reload
from fastapi import FastAPI, Request, HTTPException, Depends, status
from fastapi.responses import Response
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import httpx
import os
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# 从环境变量获取代理自身的API密钥
PROXY_API_KEY = os.getenv("PROXY_API_KEY")
# 定义HTTPBearer安全方案
security = HTTPBearer()
# 依赖函数:验证代理的API密钥
def verify_proxy_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)):
if not PROXY_API_KEY or credentials.credentials != PROXY_API_KEY:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or missing proxy API key",
headers={"WWW-Authenticate": "Bearer"},
)
return credentials.credentials
app = FastAPI(title="Gemini Proxy API")
@app.get("/")
def greet_json():
return {"Hello": "World!"}
# 3. 健康检查接口(可选,用于验证服务是否正常)
@app.get("/health")
async def health_check():
return {"status": "ok", "message": "Proxy service is running."}
# 1. 配置Gemini真实信息
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
GEMINI_BASE_URL = os.getenv("GEMINI_BASE_URL")
print(f"Using Gemini Base URL: {GEMINI_BASE_URL}")
print(f"Using Gemini API Key: {GEMINI_API_KEY}")
# 2. 通用转发接口(匹配Gemini的/predict等端点,路径动态匹配)
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy_gemini(request: Request, path: str, proxy_api_key: str = Depends(verify_proxy_api_key)): # 添加代理认证依赖
# 拼接Gemini真实请求URL
gemini_url = f"{GEMINI_BASE_URL}/{path}"
# 提取客户端请求的headers和body,透传给Gemini
client_headers = dict(request.headers)
# 移除FastAPI自带的Host头,避免Gemini校验报错
client_headers.pop("host", None)
# 将User-Agent改为curl/8.7.1,以模拟curl请求
client_headers["User-Agent"] = "curl/8.7.1"
# 添加Authorization头,用于Gemini的OpenAI兼容API
if GEMINI_API_KEY:
client_headers["Authorization"] = f"Bearer {GEMINI_API_KEY}"
try:
# 读取客户端请求体
client_body = await request.body()
# 使用httpx异步客户端发起请求
async with httpx.AsyncClient() as client:
response = await client.request(
method=request.method,
url=gemini_url,
headers=client_headers,
content=client_body,
timeout=30
)
# 将Gemini的响应透传给客户端
return Response(
content=response.content,
status_code=response.status_code,
headers=dict(response.headers)
)
except httpx.RequestError as e:
raise HTTPException(status_code=500, detail=f"转发请求失败:{str(e)}")
except httpx.HTTPStatusError as e:
raise HTTPException(status_code=e.response.status_code, detail=f"目标API返回错误:{e.response.text}")
except Exception as e:
raise HTTPException(status_code=500, detail=f"转发失败:{str(e)}")
```
### 4.4. 运行应用程序
在项目根目录,激活您的虚拟环境并运行 FastAPI 应用:
```bash
conda activate airs
uvicorn app:app --host 0.0.0.0 --port 7860 --reload
```
应用程序将在 `http://0.0.0.0:7860` 上运行。
## 5. 如何使用代理
### 5.1. 健康检查
您可以通过访问 `/health` 端点来检查代理服务是否正常运行:
```bash
curl -X GET http://0.0.0.0:7860/health
```
预期响应:
```json
{"status":"ok","message":"Proxy service is running."}
```
### 5.2. 调用 Gemini OpenAI 兼容 API
要通过代理调用 Gemini 模型(例如 `gemini-2.5-flash-preview-05-20`),您需要向代理的 `/v1/chat/completions` 端点发送一个 POST 请求,并在请求体中指定模型名称和消息。**同时,您需要在请求头中包含代理自身的 API 密钥。**
以下是一个 `curl` 命令示例(请将 `YOUR_PROXY_API_KEY` 替换为您的实际代理密钥):
```bash
curl -X POST http://0.0.0.0:7860/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_PROXY_API_KEY" \
-d '{
"model": "gemini-2.5-flash-preview-05-20",
"messages": [
{
"role": "user",
"content": "你好,请介绍一下你自己。"
}
],
"temperature": 0.7
}'
```
如果您将代理部署到 Hugging Face Spaces,例如部署在 `https://airsltd-superproxy.hf.space`,则 `curl` 命令应如下所示:
```bash
curl -X POST https://airsltd-superproxy.hf.space/v1/chat/completions \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_PROXY_API_KEY' \
--data '{
"model": "gemini-2.5-flash-preview-05-20",
"messages": [
{
"role": "user",
"content": "你好,请介绍一下你自己。"
}
],
"temperature": 0.7
}'
```
## 6. 常见问题与解决方案
* **代理认证失败 (401 Unauthorized)**
* **问题**:当您尝试调用代理时,收到 `401 Unauthorized` 错误,并提示“Invalid or missing proxy API key”。
* **原因**:这表示您没有在请求头中提供正确的 `Authorization: Bearer YOUR_PROXY_API_KEY`,或者 `PROXY_API_KEY` 环境变量未在代理部署环境中正确设置。
* **解决方案**:确保您的客户端请求包含正确的 `Authorization: Bearer YOUR_PROXY_API_KEY` 头,并且 `YOUR_PROXY_API_KEY``.env` 文件中配置的值一致。如果部署在 Hugging Face Spaces,请确保 Space 的环境变量中已设置 `PROXY_API_KEY`
* **“User location is not supported for the API use.”**:此错误来自 Gemini API,表明您的请求源 IP 地址所在的区域不受 Gemini API 支持。这通常发生在本地测试时。部署代理到支持的区域(例如 Hugging Face Spaces)可以解决此问题。
* **Postman “Error: incorrect header check”**:此错误通常是由于 Postman 自动添加的某些请求头与部署环境或代理不兼容。本项目已通过强制设置 `User-Agent: curl/8.7.1` 来尝试解决此问题。如果问题仍然存在,请检查 Postman 发送的其他请求头,并尝试禁用非必要的头部。