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