gemini-web-to-api 源码二次开发指南:Provider 接口设计与自定义扩展完整路径

原创2026-11-12 23:59:461,370 阅读

gemini-web-to-api 源码二次开发指南:Provider 接口设计与自定义扩展完整路径

gemini-web-to-api 是一个把 Google Gemini 网页端逆向为 OpenAI、Gemini、Claude 三套标准 REST API 的 Go 开源项目:用浏览器 Cookie 代替 API Key,即可在本地获得一套可直接被主流 SDK 调用的 AI 网关。如果你想在这个项目上做源码二次开发——接入新的模型服务、改造会话逻辑或扩展多模态能力——那么全文只需读懂一条主线:Provider 接口。本文带你完整走一遍这条自定义扩展路径。

项目架构速览:一次请求如何流过三套 API

整个服务基于 Go + Fiber 只负责把配置、日志和各模块交给 fx,由容器完成装配。

模块之间的接线集中在 combine_module.go 这一个文件里:

  • 协议层:openai/、gemini/、claude/ 三个模块各自暴露一套 API 路由(前缀分别为 /openai/v1、Gemini 原生路径、/claude/v1),每个模块内部分为 controller(路由)→ service(协议转换)两层
  • Provider 层:providers/ 是唯一真正"与上游对话"的地方,当前实现了 Gemini Web 客户端
  • 请求流:controller 收请求 → service 翻译成 prompt + options → providers.Client 发往 Gemini Web → 响应还原成对应协议格式返回

三套协议共享同一个底层客户端,这意味着:你在 Provider 层做的任何改动(新能力、新模型、新特性),三套 API 会同时受益。服务启动后,内置的交互式 API 文档(Scalar)会列出全部端点,并可直接 Test Request:

gemini-web-to-api 的 OpenAI 兼容 Chat Completions 端点文档页,支持 curl 一键测试

Provider 接口设计解析:7 个方法定义一切

二次开发前,先看懂契约。核心定义在 provider_interface.go,Provider 接口只有 7 个方法:

方法 职责
Init(ctx) 完成鉴权与会话建立
GenerateContent(ctx, prompt, options...) 单轮生成,支持链式选项
StartChat(options...) 开启多轮会话,返回 ChatSession
Close() 释放资源
GetName() 提供者名称(如 gemini)
IsHealthy() 健康检查,供路由层判断
ListModels() 返回可用模型列表

配合三个配套设计,接口被保持得非常"薄":

  1. 功能性选项模式:所有可调参数(模型、温度、思考级别、文件上传、视频/音乐/Canvas 配置)都通过 GenerateOption 函数式选项传入,新增参数不需要改方法签名
  2. 统一的 Response 结构:文本、推理过程、图片、视频、音频、Canvas 全部装进同一个 Response,协议层按各自格式取用即可
  3. ChatSession 独立接口:ChatSession 负责多轮对话的历史维护与元数据持久化,实现方需要维护 conversation_id 等会话状态

这套设计的妙处在于:协议层(OpenAI/Gemini/Claude)只面向接口编程,完全不感知上游是 Gemini Web 还是别的东西。

Gemini 实现拆解:Client 如何满足接口

当前唯一的生产级实现是 gemini_service.go 中的 Client 结构体,它是全文最值得精读的文件。理解它的初始化链路,你就掌握了在这个项目里做"逆向适配"的完整套路:

  1. 凭证准备:启动时读取 GEMINI_COOKIES(完整的浏览器 Cookie 头)、GEMINI_AUTH_USER(Google 多账号槽位)等环境变量,定义见 configs.go
  2. 会话刷新:Init 会先访问 google.com 补齐 Cookie,再请求 Gemini 应用页,用正则从页面中提取 SNlM0e 访问令牌、pushID、buildLabel、sessionID 等协议字段
  3. 模型发现:gemini_models.go 调用 batchexecute 的 otAQ7b RPC,拉取当前账号实际可选的模型列表(含路由用的 ModelID、Capacity、ModelNumber),并解析账号容量等级
  4. 自动保活:后台按 GEMINI_REFRESH_INTERVAL(默认 1440 分钟)轮换 Cookie、刷新会话令牌,RotateCookies 会向指定端点换取新的 __Secure-1PSIDTS

gemini-web-to-api Cookie 凭证获取指南:在 Chrome 开发者工具 Application 面板定位 __Secure-1PSID 与 __Secure-1PSIDTS

多轮对话则由 gemini_chat_session.go 实现:SendMessage 每轮把上一轮返回的 cid/rid/rcid 元数据回填进请求,从而让 Gemini Web 记住上下文——这是实现其他上游多轮会话时的关键参考。

注册与装配:Provider 如何接入依赖注入

Provider 的生命周期由两层机制管理,代码都很短,扩展时照抄即可。

第一层:工厂与管理器。 provider_manager.go 中的 Factory 是一个带读写锁的 map[string]Provider,提供 Register/Get/List 四个线程安全操作;ProviderManager 在其上增加了 SelectProvider(选定"活跃提供者")与 InitAllProviders(逐个初始化,失败不阻塞、按需重试)等编排能力。

第二层:fx 装配。 注册动作发生在 provider_module.go 的 RegisterProvider 中:把 Client 以 "gemini" 之名注册进管理器、SelectProvider("gemini") 设为默认,并在 fx 生命周期的 OnStart 钩子里后台异步初始化(避免拖慢启动),OnStop 时取消上下文并 Close。

💡 提示:NewProviderManager 的注释明确写着"no concrete imports to avoid cycles"——providers 包刻意不反向依赖具体实现,这就是为二次开发留出的扩展缝。

自定义扩展完整路径:三步接入你的 Provider

假设你要接入一个新的上游(比如某个自研网关或另一家 Web 应用),完整路径如下:

第 1 步:实现 Provider 接口。 新建一个包(或直接在 providers 下加文件),定义一个结构体实现上面 7 个方法。参考实现是 Client:把 HTTP 会话状态(令牌、Cookie、模型缓存)收敛到结构体字段,并用 sync.RWMutex 保护;GenerateContent 内部用 GenerateOption 收集配置。多轮会话则另写一个实现 ChatSession 的类型。

第 2 步:注册进管理器。 仿照 RegisterProvider,在 fx 中 fx.Provide(YourNewProvider) + fx.Invoke 里调用 pm.Register("your-name", provider)。若希望它成为默认上游,再调用 SelectProvider("your-name");否则保持多提供者共存,由上层按需 GetProvider 取用。

第 3 步:让协议层消费。 当前 openai_service.go 等 service 直接注入的是具体 *providers.Client,二次开发时建议将其改为面向 providers.Provider 接口注入(或用 ProviderManager.GetSelectedProvider()),这样任何实现都能被三套 API 复用。接口返回的 Response 填充得越完整,上层协议转换就越少改动。

验证环节同样现成:修改后运行 go test ./... 即可执行 providers/ 下大量以 fake HTTP server 模拟上游的单元测试(如 gemini_models_test.go);端到端用例见 e2e_test.go。API 面则可以直接在 Scalar 文档页(静态 OpenAPI 定义位于 openapi.json)用 Test Request 按钮逐端点验证。

常见问题与排错清单

二次开发中容易踩的坑,大多集中在鉴权与模型路由:

  • GEMINI_COOKIES is invalid or expired:Cookie 过期或残缺。按上方图示重新从开发者工具复制完整 Cookie 头;若 URL 带 /u/2/ 槽位,务必设置 GEMINI_AUTH_USER="2"
  • SNlM0e not found:会话页提取令牌失败,通常是账号未登录或 Cookie 不完整,Init 会自动尝试缓存回退 + Cookie 轮换,仍失败才报错
  • unsupported Gemini model:请求的模型名不在当前账号的发现列表中。不同账号可选模型不同,ListModels() 返回的就是真实可用集;错误信息里会列出全部可用 ID
  • 模型被静默降级:Gemini 配额耗尽时可能由低档模型应答,Client 会通过响应体里的 ModelID 识别并纠正 Response.Model,自定义实现如需保持同样行为,建议在 parseResponse 阶段做类似的路由校验
  • 初始化失败但服务没挂:这是刻意的——InitAllProviders 只告警不退出,失败的上游会在首个请求到来时按需重试

总结:一条接口,三条扩展线

回看全文,gemini-web-to-api 的源码二次开发其实收敛为三条清晰的线:

  1. 换上游:实现 Provider 接口 → 注册 → 选中,协议层零改动
  2. 加能力:在 GenerateConfig 增加选项字段 + 在 Response 增加结果字段,顺着 GenerateContent 的构建/解析链路补上协议细节
  3. 改会话:替换或增强 ChatSession 实现,管理自己的上下文元数据

理解并打通这条 Provider 扩展路径后,你获得的不仅是一个能用的 Gemini 免费 API 网关,更是一个可以用同一套接口快速复刻"Web 逆向 → 标准 API"架构的 Go 参考实现。

登录后查看全文
gemini-web-to-api