fix(ai-proxy): ensure basePathHandling works with original protocol (#3225)

This commit is contained in:
woody
2025-12-16 20:49:21 +08:00
committed by GitHub
parent 3cc745a6f5
commit 6998800c64
6 changed files with 555 additions and 5 deletions

View File

@@ -174,12 +174,14 @@ func (m *azureProvider) TransformRequestBody(ctx wrapper.HttpContext, apiName Ap
}
func (m *azureProvider) transformRequestPath(ctx wrapper.HttpContext, apiName ApiName) string {
originalPath := util.GetOriginalRequestPath()
// When using original protocol, don't overwrite the path.
// This ensures basePathHandling works correctly even in TransformRequestBody stage.
if m.config.IsOriginal() {
return originalPath
return ""
}
originalPath := util.GetOriginalRequestPath()
if m.serviceUrlType == azureServiceUrlTypeFull {
log.Debugf("azureProvider: use configured path %s", m.serviceUrlFullPath)
return m.serviceUrlFullPath

View File

@@ -106,8 +106,11 @@ func (m *minimaxProvider) handleRequestBodyByChatCompletionPro(body []byte) (typ
}
// Map the model and rewrite the request path.
// When using original protocol, don't overwrite the path to ensure basePathHandling works correctly.
request.Model = getMappedModel(request.Model, m.config.modelMapping)
_ = util.OverwriteRequestPath(fmt.Sprintf("%s?GroupId=%s", minimaxChatCompletionProPath, m.config.minimaxGroupId))
if !m.config.IsOriginal() {
_ = util.OverwriteRequestPath(fmt.Sprintf("%s?GroupId=%s", minimaxChatCompletionProPath, m.config.minimaxGroupId))
}
if m.config.context == nil {
minimaxRequest := m.buildMinimaxChatCompletionProRequest(request, "")

View File

@@ -973,12 +973,33 @@ func (c *ProviderConfig) handleRequestBody(
func (c *ProviderConfig) handleRequestHeaders(provider Provider, ctx wrapper.HttpContext, apiName ApiName) {
headers := util.GetRequestHeaders()
originPath := headers.Get(":path")
// Record the path after removePrefix processing
var removePrefixPath string
if c.basePath != "" && c.basePathHandling == basePathHandlingRemovePrefix {
headers.Set(":path", strings.TrimPrefix(originPath, c.basePath))
removePrefixPath = strings.TrimPrefix(originPath, c.basePath)
headers.Set(":path", removePrefixPath)
}
if handler, ok := provider.(TransformRequestHeadersHandler); ok {
handler.TransformRequestHeaders(ctx, apiName, headers)
}
// When using original protocol with removePrefix, restore the basePath-processed path.
// This ensures basePathHandling works correctly even when TransformRequestHeaders
// overwrites the path (which most providers do).
//
// TODO: Most providers (OpenAI, vLLM, DeepSeek, Claude, etc.) unconditionally overwrite
// the path in TransformRequestHeaders without checking IsOriginal(). Ideally, each provider
// should check IsOriginal() before overwriting the path (like Qwen does). Once all providers
// are updated to handle protocol correctly, this workaround can be removed.
// Affected providers: OpenAI, vLLM, ZhipuAI, Moonshot, Longcat, DeepSeek, Azure, Yi,
// TogetherAI, Stepfun, Ollama, Hunyuan, GitHub, Doubao, Cohere, Baichuan, AI360, Claude,
// Groq, Grok, Spark, Fireworks, Cloudflare, Baidu, OpenRouter, DeepL (24+ providers)
if c.IsOriginal() && removePrefixPath != "" {
headers.Set(":path", removePrefixPath)
}
if c.basePath != "" && c.basePathHandling == basePathHandlingPrepend && !strings.HasPrefix(headers.Get(":path"), c.basePath) {
headers.Set(":path", path.Join(c.basePath, headers.Get(":path")))
}