Skip to content

fix: 修复 buildProxyUrl 重复拼接版本前缀的问题(Gemini)#693

Merged
ding113 merged 3 commits intoding113:devfrom
sunxyw:fix-proxy-url-detection-for-gemini
Feb 2, 2026
Merged

fix: 修复 buildProxyUrl 重复拼接版本前缀的问题(Gemini)#693
ding113 merged 3 commits intoding113:devfrom
sunxyw:fix-proxy-url-detection-for-gemini

Conversation

@sunxyw
Copy link
Contributor

@sunxyw sunxyw commented Feb 1, 2026

Summary

Fix buildProxyUrl incorrectly duplicating API version prefixes (like /v1beta, /v1internal) when baseUrl already contains the full endpoint path. This issue primarily affects Gemini endpoints but the fix applies to all providers.

修复 buildProxyUrlbaseUrl 已包含完整端点路径时错误地重复拼接 API 版本前缀(如 /v1beta/v1internal)的问题。此问题主要影响 Gemini 端点,但修复适用于所有供应商。

Problem

Previously addressed for OpenAI in #690 and #139, but custom Gemini endpoints still exhibited the bug.

When baseUrl contains a complete path (e.g., /models), buildProxyUrl incorrectly duplicates the version prefix from the request path.

Example (Gemini endpoint):

  • Input: baseUrl="https://co.yes.vg/gemini/models", requestUrl="/v1beta/models/gemini-1.5-pro:streamGenerateContent"
  • Current output: https://co.yes.vg/gemini/models/v1beta/models/gemini-1.5-pro:streamGenerateContent
  • Expected output: https://co.yes.vg/gemini/models/gemini-1.5-pro:streamGenerateContent

Related Issues:

Solution

Replace the hardcoded /v1 prefix logic with a dynamic regex pattern that:

  • Matches and strips API version prefixes: /v1, /v1beta, /v1internal, /v2, etc.
  • Uses the pattern /v\d+[a-z0-9]* to support current and future version formats
  • Preserves the suffix path after stripping the version prefix
  • Only applies when baseUrl ends with the target endpoint (e.g., /models, /messages)

This ensures compatibility with:

  • Google Gemini API (/v1beta, /v1internal)
  • Anthropic Claude API (/v1)
  • OpenAI API (/v1)
  • Custom proxy endpoints with any version format

Changes

Core Changes

  • src/app/v1/_lib/url.ts: Refactored version prefix detection logic
    • Changed from hardcoded /v1 to dynamic regex /v\d+[a-z0-9]*/
    • Unified endpoint matching logic with captured groups
    • Added regex escaping for endpoint patterns

Supporting Changes

  • tests/unit/app/v1/url.test.ts: Added regression tests
    • Test case for Gemini /v1beta prefix stripping
    • Test case for /v1internal variant (used by Gemini 2.5)
    • Test case for future version formats like /v2

Testing

Automated Tests

  • Unit tests added for /v1beta, /v1internal, /v2 variants
  • All existing tests pass
  • Edge cases covered (various endpoint types)

Manual Testing

Verified with Gemini custom endpoints:

  1. Configure provider with baseUrl="https://custom-proxy.example.com/gemini/models"
  2. Send request to /v1beta/models/gemini-1.5-pro:streamGenerateContent
  3. Verify upstream URL is https://custom-proxy.example.com/gemini/models/gemini-1.5-pro:streamGenerateContent (no duplicate /v1beta)

Checklist

  • Code follows project conventions
  • Self-review completed
  • Tests pass locally (bun run test)
  • No breaking changes
  • Regression tests added

Description enhanced by Claude AI

Greptile Overview

Greptile Summary

This PR successfully extends the URL builder to support dynamic API version prefixes beyond the hardcoded /v1 pattern. The refactoring replaces string-based prefix detection with a regex pattern that matches /v1, /v1beta, /v1internal, /v2, and future version formats using /v\d+[a-z0-9]*.

Key Changes:

  • Moved endpoint definitions and regex compilation to module scope for efficient reuse
  • Introduced escapeRegExp utility for safe regex pattern construction
  • Replaced hardcoded /v1 logic with dynamic version extraction using named capture groups
  • Added comprehensive test coverage for Gemini-specific version formats

Issues Found:

  • The regex pattern /v\d+[a-z0-9]* is overly permissive and could match unconventional version strings like v1xyz999, though this is unlikely to cause issues in practice
  • Minor inefficiency in variable extraction order (suffix extracted before conditional check)

The core logic correctly handles version prefix stripping when baseUrl already contains the target endpoint, preventing URL duplication issues that previously affected Gemini and other providers.

Confidence Score: 4/5

  • Safe to merge with minor style improvements recommended
  • The implementation correctly solves the version prefix duplication problem with good test coverage. Regex compilation is efficiently done at module scope. The pattern is slightly over-permissive but won't cause functional issues. No breaking changes or security concerns.
  • No files require special attention - both implementation and tests are solid

Important Files Changed

Filename Overview
src/app/v1/_lib/url.ts Refactored version prefix detection from hardcoded /v1 to dynamic regex pattern supporting multiple version formats (/v1beta, /v1internal, /v2)
tests/unit/app/v1/url.test.ts Added comprehensive test coverage for new version prefix patterns (/v1beta, /v1internal, /v2)

Sequence Diagram

sequenceDiagram
    participant Client
    participant Proxy as buildProxyUrl
    participant Regex as endpointRegexes
    participant Target as Target API

    Client->>Proxy: Request with /v1beta/models/gemini-1.5-pro
    Note over Proxy: baseUrl="https://api.example.com/gemini/models"
    
    Proxy->>Proxy: Parse baseUrl & requestPath
    Proxy->>Proxy: Check Case 1: exact prefix match
    Note over Proxy: Not matched
    
    Proxy->>Regex: Loop through endpoint patterns
    Regex->>Regex: Match /v1beta/models/gemini-1.5-pro against<br/>^/(v\d+[a-z0-9]*)/models(?<suffix>/.*)?$
    Regex-->>Proxy: Match found: version="v1beta", suffix="/gemini-1.5-pro"
    
    Proxy->>Proxy: Check if basePath ends with "/models"
    Note over Proxy: Condition satisfied
    
    Proxy->>Proxy: Construct: basePath + suffix
    Note over Proxy: Result: /gemini/models/gemini-1.5-pro
    
    Proxy->>Target: Forward to https://api.example.com/gemini/models/gemini-1.5-pro
    Note over Target: Version prefix stripped ✓
Loading

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @sunxyw, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在解决 buildProxyUrl 函数中一个长期存在的问题,即在构建代理 URL 时,API 版本前缀会被错误地重复添加,尤其影响到自定义 Gemini 端点。通过引入基于正则表达式的解析机制,该函数现在能够正确识别并处理各种版本前缀,从而确保生成的 URL 格式正确,避免了因 URL 结构错误导致的请求失败。这项改进显著提升了 API 调用的可靠性,特别是对于使用不同版本方案的服务。

Highlights

  • 修复重复拼接版本前缀问题: 解决了 buildProxyUrl 函数在 baseUrl 已包含完整路径时,错误地将请求路径中的 API 版本前缀(如 /v1beta)重复拼接的问题。此问题曾影响自定义 Gemini 端点。
  • 引入正则表达式处理版本前缀: 通过使用正则表达式动态匹配并剥离请求路径中的 API 版本前缀(包括但不限于 /v1/v1beta/v1internal),使 URL 构建逻辑更加健壮和灵活。
  • 新增单元测试: 为确保修复的正确性及未来兼容性,新增了多个单元测试,覆盖了 baseUrl/models 结尾时去除请求中版本前缀的场景,并支持 v1internalv2 等未来版本前缀。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Feb 1, 2026

📝 Walkthrough

Walkthrough

修改 URL 构建逻辑:用正则检测并提取请求路径中的版本前缀(如 /v1、/v1beta、/v1internal、/v2 等),基于捕获的版本与端点动态构建 requestRoot,替换原先固定拼接 /v1 的行为;并新增单元测试覆盖多版本场景。

Changes

Cohort / File(s) Summary
URL 处理逻辑重构
src/app/v1/_lib/url.ts
引入 targetEndpoints 与对应正则 endpointRegexes,新增 escapeRegExp,用捕获组提取版本并基于该版本动态构建 requestRoot(替换固定 /v1${endpoint} 的方案),保留回退拼接与错误处理;添加调试与说明注释。
单元测试扩展
tests/unit/app/v1/url.test.ts
新增三项测试,验证当 baseUrl/models 结尾时,能正确处理请求 URL 中的 v1betav1internalv2 等版本前缀,确保最终组合的目标 URL 正确且不重复插入或丢失版本段。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR 标题清晰地概括了主要改动:修复 buildProxyUrl 重复拼接版本前缀的问题,特别针对 Gemini 端点,反映了变更集的核心改进。
Linked Issues check ✅ Passed 代码变更完全满足关联问题 #690#139 的需求:动态正则表达式支持多版本格式(/v1、/v1beta、/v1internal、/v2),允许用户提供完整的自定义端点,避免强制添加版本前缀。
Out of Scope Changes check ✅ Passed 所有代码变更均在范围内:src/app/v1/_lib/url.ts 重构版本前缀检测逻辑,tests/unit/app/v1/url.test.ts 添加回归测试,与关联问题的目标一致,无超出范围的改动。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed PR description clearly describes the bug (version prefix duplication), provides concrete examples, explains the solution (dynamic regex pattern), and documents changes to implementation and tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sunxyw sunxyw changed the base branch from main to dev February 1, 2026 07:37
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次 PR 修复了 buildProxyUrlbaseUrl 已包含完整路径时,会重复拼接版本前缀的问题。通过使用正则表达式动态匹配和剥离 API 版本前缀,该修复方案不仅解决了 Gemini 端点的问题,也增强了对未来其他类似端点的兼容性。代码逻辑清晰,并且补充了充分的单元测试来覆盖修复的场景。整体来看,这是一个高质量的修复。我有一个关于代码组织结构的小建议,请见具体评论。

@github-actions github-actions bot added bug Something isn't working area:Google Gemini area:provider size/XS Extra Small PR (< 50 lines) labels Feb 1, 2026
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

No significant issues identified in this PR. The implementation correctly addresses the Gemini version prefix duplication issue using a robust regex-based approach.

PR Size: XS

  • Lines changed: 65 (49 additions, 16 deletions)
  • Files changed: 2

Analysis Results

The PR introduces a dynamic version detection mechanism using regex to strip API version prefixes (v1, v1beta, v1internal, etc.) from request paths before URL construction. This prevents duplicate path segments when baseUrl already contains the complete endpoint path.

Key Changes:

  • Replaced hardcoded /v1 prefix with dynamic regex pattern /(v\d+[a-z0-9]*)
  • Properly handles version variants: v1, v1beta, v1internal, v2, etc.
  • Maintains backward compatibility with existing OpenAI fix (#139)
  • Three new test cases cover the main scenarios

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (existing try-catch preserved)
  • Type safety - Clean (proper use of optional chaining and nullish coalescing)
  • Documentation accuracy - Clean (inline comments match implementation)
  • Test coverage - Adequate (3 new tests covering v1beta, v1internal, v2)
  • Code clarity - Good (regex escaping helper improves readability)

Automated review by Claude AI

- Move escapeRegExp helper to module scope to avoid recreation
- Remove case-insensitive flag from version endpoint regex
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Move endpoint regex compilation outside the loop to avoid repeated regex creation on every request. Pre-compile endpoint patterns at module load time for better performance.
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@ding113 ding113 merged commit cdeb79a into ding113:dev Feb 2, 2026
8 of 10 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Feb 2, 2026
@sunxyw sunxyw deleted the fix-proxy-url-detection-for-gemini branch February 2, 2026 08:40
github-actions bot pushed a commit that referenced this pull request Feb 2, 2026
* fix: 修复 buildProxyUrl 重复拼接版本前缀的问题

* refactor(proxy): optimize regex compilation in buildProxyUrl

- Move escapeRegExp helper to module scope to avoid recreation
- Remove case-insensitive flag from version endpoint regex

* refactor(proxy): optimize endpoint regex compilation in URL builder

Move endpoint regex compilation outside the loop to avoid repeated regex creation on every request. Pre-compile endpoint patterns at module load time for better performance.
@github-actions github-actions bot mentioned this pull request Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Google Gemini area:provider bug Something isn't working size/XS Extra Small PR (< 50 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants