# 使用 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 发送的其他请求头,并尝试禁用非必要的头部。