feat(ai-proxy): add basePathHandling option (#2535)

Co-authored-by: Se7en <chengzw258@163.com>
This commit is contained in:
woody
2025-07-03 20:34:14 +08:00
committed by GitHub
parent 45eb76d4cc
commit 0996ad21b1

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"math/rand" "math/rand"
"net/http" "net/http"
"path"
"regexp" "regexp"
"strings" "strings"
@@ -18,8 +19,9 @@ import (
) )
type ( type (
ApiName string ApiName string
Pointcut string Pointcut string
basePathHandling string
) )
const ( const (
@@ -143,6 +145,9 @@ const (
wildcard = "*" wildcard = "*"
defaultTimeout = 2 * 60 * 1000 // ms defaultTimeout = 2 * 60 * 1000 // ms
basePathHandlingRemovePrefix basePathHandling = "removePrefix"
basePathHandlingPrepend basePathHandling = "prepend"
) )
type providerInitializer interface { type providerInitializer interface {
@@ -358,8 +363,10 @@ type ProviderConfig struct {
// @Title zh-CN 额外支持的ai能力 // @Title zh-CN 额外支持的ai能力
// @Description zh-CN 开放的ai能力和urlpath映射例如 {"openai/v1/chatcompletions": "/v1/chat/completions"} // @Description zh-CN 开放的ai能力和urlpath映射例如 {"openai/v1/chatcompletions": "/v1/chat/completions"}
capabilities map[string]string capabilities map[string]string
// @Title zh-CN 如果配置了subPath将会先移除请求path中该前缀再进行后续处理 // @Title zh-CN 如果配置了basePath可用于在请求path中移除该前缀,或添加至请求path中默认为进行移除
subPath string `required:"false" yaml:"subPath" json:"subPath"` basePath string `required:"false" yaml:"basePath" json:"basePath"`
// @Title zh-CN basePathHandling用于指定basePath的处理方式可选值removePrefix、prepend
basePathHandling basePathHandling `required:"false" yaml:"basePathHandling" json:"basePathHandling"`
} }
func (c *ProviderConfig) GetId() string { func (c *ProviderConfig) GetId() string {
@@ -527,7 +534,11 @@ func (c *ProviderConfig) FromJson(json gjson.Result) {
c.capabilities[capability] = pathJson.String() c.capabilities[capability] = pathJson.String()
} }
} }
c.subPath = json.Get("subPath").String() c.basePath = json.Get("basePath").String()
c.basePathHandling = basePathHandling(json.Get("basePathHandling").String())
if c.basePath != "" && c.basePathHandling == "" {
c.basePathHandling = basePathHandlingRemovePrefix
}
} }
func (c *ProviderConfig) Validate() error { func (c *ProviderConfig) Validate() error {
@@ -839,12 +850,15 @@ func (c *ProviderConfig) handleRequestBody(
func (c *ProviderConfig) handleRequestHeaders(provider Provider, ctx wrapper.HttpContext, apiName ApiName) { func (c *ProviderConfig) handleRequestHeaders(provider Provider, ctx wrapper.HttpContext, apiName ApiName) {
headers := util.GetOriginalRequestHeaders() headers := util.GetOriginalRequestHeaders()
originPath := headers.Get(":path") originPath := headers.Get(":path")
if c.subPath != "" { if c.basePath != "" && c.basePathHandling == basePathHandlingRemovePrefix {
headers.Set(":path", strings.TrimPrefix(originPath, c.subPath)) headers.Set(":path", strings.TrimPrefix(originPath, c.basePath))
} }
if handler, ok := provider.(TransformRequestHeadersHandler); ok { if handler, ok := provider.(TransformRequestHeadersHandler); ok {
handler.TransformRequestHeaders(ctx, apiName, headers) handler.TransformRequestHeaders(ctx, apiName, headers)
} }
if c.basePath != "" && c.basePathHandling == basePathHandlingPrepend && !strings.HasPrefix(headers.Get(":path"), c.basePath) {
headers.Set(":path", path.Join(c.basePath, headers.Get(":path")))
}
if headers.Get(":path") != originPath { if headers.Get(":path") != originPath {
headers.Set("X-ENVOY-ORIGINAL-PATH", originPath) headers.Set("X-ENVOY-ORIGINAL-PATH", originPath)
} }