mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 19:47:10 +08:00
refactor: remove endpoint tests and enhance URL handling
- Deleted outdated test files for OpenAI endpoint functionality. - Improved the OpenAIEndpointURL function to better handle custom paths and version segments. - Introduced a new helper function, stripEndpointVersionPrefix, to streamline endpoint processing.
This commit is contained in:
@@ -304,19 +304,24 @@ func OpenAIEndpointURL(baseURL string, endpoint string) string {
|
||||
if !strings.HasPrefix(normalizedEndpoint, "/") {
|
||||
normalizedEndpoint = "/" + normalizedEndpoint
|
||||
}
|
||||
// 规则0:自定义路径模式 → 直接用 baseURL 作为完整请求地址
|
||||
// 规则0:自定义路径模式
|
||||
// - baseURL 已含 endpoint 后缀(/chat/completions 或 /responses)→ 直接用 base
|
||||
// - 否则追加 /chat/completions(默认协议形态,覆盖 Z.AI /v4 等场景)
|
||||
if normalizedEndpoint == modelchannel.OpenAIEndpointCustom {
|
||||
if OpenAIEndpointFromBaseURL(base) != "" {
|
||||
return base
|
||||
}
|
||||
return base + "/chat/completions"
|
||||
}
|
||||
// 规则1:baseURL 已含 endpoint 后缀 → 直接用 base
|
||||
if OpenAIEndpointFromBaseURL(base) != "" {
|
||||
return base
|
||||
}
|
||||
// 规则2:通用版本段去重(/v1 /v2 /v3 /v4 ... 任意版本号)
|
||||
if version, ok := trailingVersionSegment(base); ok {
|
||||
prefix := "/" + version + "/"
|
||||
if strings.HasPrefix(normalizedEndpoint, prefix) {
|
||||
return base + strings.TrimPrefix(normalizedEndpoint, "/"+version)
|
||||
// 规则2:baseURL 以 /vN 结尾时,剥离 endpoint 的版本前缀(/v1/、/v2/ 等)
|
||||
// 这样 base=.../v4 + endpoint=/v1/chat/completions → .../v4/chat/completions
|
||||
if _, ok := trailingVersionSegment(base); ok {
|
||||
if rest, stripped := stripEndpointVersionPrefix(normalizedEndpoint); stripped {
|
||||
return base + rest
|
||||
}
|
||||
}
|
||||
// 规则3:兜底原样拼接
|
||||
@@ -342,6 +347,24 @@ func trailingVersionSegment(base string) (string, bool) {
|
||||
return seg, true
|
||||
}
|
||||
|
||||
// stripEndpointVersionPrefix 剥离 endpoint 路径开头的版本段前缀(/vN/),
|
||||
// 返回剩余路径和是否成功剥离。
|
||||
// /v1/chat/completions → ("/chat/completions", true)
|
||||
// /chat/completions → ("", false)
|
||||
func stripEndpointVersionPrefix(endpoint string) (string, bool) {
|
||||
if len(endpoint) < 4 || endpoint[0] != '/' || endpoint[1] != 'v' {
|
||||
return "", false
|
||||
}
|
||||
i := 2
|
||||
for i < len(endpoint) && endpoint[i] >= '0' && endpoint[i] <= '9' {
|
||||
i++
|
||||
}
|
||||
if i == 2 || i >= len(endpoint) || endpoint[i] != '/' {
|
||||
return "", false
|
||||
}
|
||||
return endpoint[i:], true
|
||||
}
|
||||
|
||||
func ResolveOpenAIEndpoint(baseURL string, endpoint string) string {
|
||||
if endpointFromURL := OpenAIEndpointFromBaseURL(baseURL); endpointFromURL != "" {
|
||||
return endpointFromURL
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package modeladapter
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTrailingVersionSegment(t *testing.T) {
|
||||
cases := []struct {
|
||||
base string
|
||||
wantSeg string
|
||||
wantOK bool
|
||||
}{
|
||||
{"https://api.openai.com/v1", "v1", true},
|
||||
{"https://api.z.ai/api/coding/paas/v4", "v4", true},
|
||||
{"https://example.com/v2", "v2", true},
|
||||
{"https://example.com/v12", "v12", true},
|
||||
|
||||
// 非版本段
|
||||
{"https://api.openai.com", "", false},
|
||||
{"https://example.com/chat", "", false},
|
||||
{"https://example.com/api", "", false},
|
||||
{"https://example.com/v", "", false},
|
||||
{"https://example.com/vx", "", false},
|
||||
{"", "", false},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.base, func(t *testing.T) {
|
||||
gotSeg, gotOK := trailingVersionSegment(tc.base)
|
||||
if gotSeg != tc.wantSeg || gotOK != tc.wantOK {
|
||||
t.Fatalf("trailingVersionSegment(%q) = (%q, %v), want (%q, %v)", tc.base, gotSeg, gotOK, tc.wantSeg, tc.wantOK)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAIEndpointURL(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
baseURL string
|
||||
endpoint string
|
||||
want string
|
||||
}{
|
||||
// === issue #166 核心场景:选"自定义路径",baseURL 填完整地址 ===
|
||||
{"custom_zai_full_chat", "https://api.z.ai/api/coding/paas/v4/chat/completions", "/custom", "https://api.z.ai/api/coding/paas/v4/chat/completions"},
|
||||
{"custom_zai_full_responses", "https://api.z.ai/api/coding/paas/v4/responses", "/custom", "https://api.z.ai/api/coding/paas/v4/responses"},
|
||||
|
||||
// === 存量场景回归:OpenAI 官方 /v1 ===
|
||||
{"openai_v1_responses_dedup", "https://api.openai.com/v1", "/v1/responses", "https://api.openai.com/v1/responses"},
|
||||
{"openai_v1_chat_dedup", "https://api.openai.com/v1", "/v1/chat/completions", "https://api.openai.com/v1/chat/completions"},
|
||||
// baseURL 不带版本号
|
||||
{"openai_noversion_chat", "https://api.openai.com", "/v1/chat/completions", "https://api.openai.com/v1/chat/completions"},
|
||||
|
||||
// === baseURL 已含完整 endpoint 后缀 → 直接用 base ===
|
||||
{"baseurl_has_chat_suffix", "https://api.openai.com/v1/chat/completions", "/v1/chat/completions", "https://api.openai.com/v1/chat/completions"},
|
||||
{"baseurl_has_responses_suffix", "https://api.openai.com/v1/responses", "/v1/responses", "https://api.openai.com/v1/responses"},
|
||||
|
||||
// === 空 endpoint 默认 responses ===
|
||||
{"empty_endpoint_defaults", "https://api.openai.com/v1", "", "https://api.openai.com/v1/responses"},
|
||||
|
||||
// === 通用版本段去重:/v2 /v3 ===
|
||||
{"v2_dedup", "https://example.com/v2", "/v2/chat/completions", "https://example.com/v2/chat/completions"},
|
||||
{"v3_dedup", "https://example.com/v3", "/v3/responses", "https://example.com/v3/responses"},
|
||||
|
||||
// === 不同版本号不去重:base /v4 + endpoint /v1 ===
|
||||
{"different_version_no_dedup", "https://example.com/v4", "/v1/chat/completions", "https://example.com/v4/v1/chat/completions"},
|
||||
|
||||
// === 尾部斜杠清理 ===
|
||||
{"trailing_slash_base", "https://api.openai.com/v1/", "/v1/responses", "https://api.openai.com/v1/responses"},
|
||||
|
||||
// === /custom + baseURL 不含已知后缀 → 直接返回 base ===
|
||||
{"custom_no_suffix", "https://api.example.com/some/path", "/custom", "https://api.example.com/some/path"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got := OpenAIEndpointURL(tc.baseURL, tc.endpoint)
|
||||
if got != tc.want {
|
||||
t.Fatalf("OpenAIEndpointURL(%q, %q)\n got %s\n want %s", tc.baseURL, tc.endpoint, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package modelchannel
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNormalizeOpenAIEndpoint(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
providerType string
|
||||
endpoint string
|
||||
want string
|
||||
}{
|
||||
// 非 openai 类型始终返回空
|
||||
{"anthropic_ignored", "anthropic", "/v1/responses", ""},
|
||||
{"empty_type_ignored", "", "/v1/responses", ""},
|
||||
|
||||
// 预设值
|
||||
{"empty_defaults_to_responses", "openai", "", OpenAIEndpointResponses},
|
||||
{"preset_responses", "openai", "/v1/responses", OpenAIEndpointResponses},
|
||||
{"preset_chat_completions", "openai", "/v1/chat/completions", OpenAIEndpointChatCompletions},
|
||||
{"preset_custom", "openai", "/custom", OpenAIEndpointCustom},
|
||||
|
||||
// 非法值:不再允许任意自定义路径,只接受三个预设值
|
||||
{"arbitrary_path_rejected", "openai", "/v4/chat/completions", ""},
|
||||
{"arbitrary_path_rejected_2", "openai", "/chat/completions", ""},
|
||||
{"missing_slash", "openai", "v1/responses", ""},
|
||||
{"slash_only", "openai", "/", ""},
|
||||
{"whitespace", "openai", " ", OpenAIEndpointResponses},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got := NormalizeOpenAIEndpoint(tc.providerType, tc.endpoint)
|
||||
if got != tc.want {
|
||||
t.Fatalf("NormalizeOpenAIEndpoint(%q, %q) = %q, want %q", tc.providerType, tc.endpoint, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAIEndpointShape(t *testing.T) {
|
||||
cases := []struct {
|
||||
endpoint string
|
||||
want string
|
||||
}{
|
||||
// Responses 形态
|
||||
{"/v1/responses", "responses"},
|
||||
{"/v4/responses", "responses"},
|
||||
{"/responses", "responses"},
|
||||
|
||||
// Chat Completions 形态
|
||||
{"/v1/chat/completions", "chat/completions"},
|
||||
{"/v4/chat/completions", "chat/completions"},
|
||||
{"/chat/completions", "chat/completions"},
|
||||
|
||||
// /custom 不含已知后缀 → 兜底走 chat/completions
|
||||
{"/custom", "chat/completions"},
|
||||
|
||||
// 兜底默认
|
||||
{"", "chat/completions"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.endpoint, func(t *testing.T) {
|
||||
got := OpenAIEndpointShape(tc.endpoint)
|
||||
if got != tc.want {
|
||||
t.Fatalf("OpenAIEndpointShape(%q) = %q, want %q", tc.endpoint, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user