From 6b2e5e07cc99165a59ace21c88f1e1baa65ebc27 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 16 Apr 2026 21:36:48 +0800 Subject: [PATCH] test(proxy/gemini): pin non-full-URL versioned relay base stripping Adds two regression tests that lock in the intentional asymmetry between full-URL and non-full-URL modes: - Full-URL mode: opaque base path (e.g. `https://relay.example/custom/v1beta`) is preserved verbatim. Already covered by `preserves_opaque_full_url_with_bare_v1beta_suffix`. - Non-full-URL mode: base path MUST strip `/v1`, `/v1beta`, etc. so the standard `/v1beta/models/{model}:method` endpoint can be appended without producing a doubled `/v1beta/v1beta/models/...` path. The non-full-URL contract is "base URL + cc-switch appends the canonical Gemini endpoint". A user who needs a relay's custom namespace (e.g. `/v1/models/...`) must use full-URL mode and paste the complete method path. This commit adds regression coverage so a future attempt to mirror full-URL's host-whitelist gating into `normalize_gemini_base_path` will fail the test suite immediately. --- src-tauri/src/proxy/gemini_url.rs | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src-tauri/src/proxy/gemini_url.rs b/src-tauri/src/proxy/gemini_url.rs index 46c2c0775..c75136677 100644 --- a/src-tauri/src/proxy/gemini_url.rs +++ b/src-tauri/src/proxy/gemini_url.rs @@ -566,6 +566,48 @@ mod tests { ); } + /// Regression guard: in non-full-URL mode, a versioned third-party + /// relay base must have its `/v1beta` suffix **stripped** so the + /// appended standard endpoint (`/v1beta/models/{model}:method`) does + /// not produce a doubled `/v1beta/v1beta/models/...` path. Non-full + /// mode's contract is "base URL + cc-switch appends the canonical + /// Gemini endpoint" — a user who wants a relay's custom namespace + /// (e.g. `/v1/models/...`) must use full-URL mode instead. + /// + /// This test pins the intentional asymmetry with + /// `preserves_opaque_full_url_with_bare_v1beta_suffix` (full-URL + /// preserves, non-full strips) so nobody "fixes" one side into + /// breaking the other. + #[test] + fn strips_versioned_relay_base_suffix_in_non_full_url_mode() { + let url = resolve_gemini_native_url( + "https://relay.example/custom/v1beta", + "/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse", + false, + ); + + assert_eq!( + url, + "https://relay.example/custom/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse" + ); + } + + /// Companion case: `/v1` base suffix also stripped in non-full-URL + /// mode regardless of host. + #[test] + fn strips_v1_relay_base_suffix_in_non_full_url_mode() { + let url = resolve_gemini_native_url( + "https://relay.example/custom/v1", + "/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse", + false, + ); + + assert_eq!( + url, + "https://relay.example/custom/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse" + ); + } + // ------------------------------------------------------------------ // Model ID normalization tests. //