mirror of
https://github.com/alibaba/higress.git
synced 2026-06-09 04:37:31 +08:00
fix: Fix possible type-casting related panics in ai-proxy plugin (#1127)
This commit is contained in:
@@ -99,7 +99,7 @@ func onHttpRequestBody(ctx wrapper.HttpContext, pluginConfig config.PluginConfig
|
|||||||
log.Debugf("[onHttpRequestBody] provider=%s", activeProvider.GetProviderType())
|
log.Debugf("[onHttpRequestBody] provider=%s", activeProvider.GetProviderType())
|
||||||
|
|
||||||
if handler, ok := activeProvider.(provider.RequestBodyHandler); ok {
|
if handler, ok := activeProvider.(provider.RequestBodyHandler); ok {
|
||||||
apiName := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
apiName, _ := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
||||||
action, err := handler.OnRequestBody(ctx, apiName, body, log)
|
action, err := handler.OnRequestBody(ctx, apiName, body, log)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return action
|
return action
|
||||||
@@ -139,7 +139,7 @@ func onHttpResponseHeaders(ctx wrapper.HttpContext, pluginConfig config.PluginCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if handler, ok := activeProvider.(provider.ResponseHeadersHandler); ok {
|
if handler, ok := activeProvider.(provider.ResponseHeadersHandler); ok {
|
||||||
apiName := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
apiName, _ := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
||||||
action, err := handler.OnResponseHeaders(ctx, apiName, log)
|
action, err := handler.OnResponseHeaders(ctx, apiName, log)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return action
|
return action
|
||||||
@@ -171,7 +171,7 @@ func onStreamingResponseBody(ctx wrapper.HttpContext, pluginConfig config.Plugin
|
|||||||
log.Debugf("isLastChunk=%v chunk: %s", isLastChunk, string(chunk))
|
log.Debugf("isLastChunk=%v chunk: %s", isLastChunk, string(chunk))
|
||||||
|
|
||||||
if handler, ok := activeProvider.(provider.StreamingResponseBodyHandler); ok {
|
if handler, ok := activeProvider.(provider.StreamingResponseBodyHandler); ok {
|
||||||
apiName := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
apiName, _ := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
||||||
modifiedChunk, err := handler.OnStreamingResponseBody(ctx, apiName, chunk, isLastChunk, log)
|
modifiedChunk, err := handler.OnStreamingResponseBody(ctx, apiName, chunk, isLastChunk, log)
|
||||||
if err == nil && modifiedChunk != nil {
|
if err == nil && modifiedChunk != nil {
|
||||||
return modifiedChunk
|
return modifiedChunk
|
||||||
@@ -193,7 +193,7 @@ func onHttpResponseBody(ctx wrapper.HttpContext, pluginConfig config.PluginConfi
|
|||||||
//log.Debugf("response body: %s", string(body))
|
//log.Debugf("response body: %s", string(body))
|
||||||
|
|
||||||
if handler, ok := activeProvider.(provider.ResponseBodyHandler); ok {
|
if handler, ok := activeProvider.(provider.ResponseBodyHandler); ok {
|
||||||
apiName := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
apiName, _ := ctx.GetContext(ctxKeyApiName).(provider.ApiName)
|
||||||
action, err := handler.OnResponseBody(ctx, apiName, body, log)
|
action, err := handler.OnResponseBody(ctx, apiName, body, log)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return action
|
return action
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ func (b *baiduProvider) responseBaidu2OpenAI(ctx wrapper.HttpContext, response *
|
|||||||
return &chatCompletionResponse{
|
return &chatCompletionResponse{
|
||||||
Id: response.Id,
|
Id: response.Id,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletion,
|
Object: objectChatCompletion,
|
||||||
Choices: []chatCompletionChoice{choice},
|
Choices: []chatCompletionChoice{choice},
|
||||||
@@ -321,7 +321,7 @@ func (b *baiduProvider) streamResponseBaidu2OpenAI(ctx wrapper.HttpContext, resp
|
|||||||
return &chatCompletionResponse{
|
return &chatCompletionResponse{
|
||||||
Id: response.Id,
|
Id: response.Id,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletion,
|
Object: objectChatCompletion,
|
||||||
Choices: []chatCompletionChoice{choice},
|
Choices: []chatCompletionChoice{choice},
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ func (c *claudeProvider) responseClaude2OpenAI(ctx wrapper.HttpContext, origResp
|
|||||||
return &chatCompletionResponse{
|
return &chatCompletionResponse{
|
||||||
Id: origResponse.Id,
|
Id: origResponse.Id,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletion,
|
Object: objectChatCompletion,
|
||||||
Choices: []chatCompletionChoice{choice},
|
Choices: []chatCompletionChoice{choice},
|
||||||
@@ -356,7 +356,7 @@ func createChatCompletionResponse(ctx wrapper.HttpContext, response *claudeTextG
|
|||||||
return &chatCompletionResponse{
|
return &chatCompletionResponse{
|
||||||
Id: response.Message.Id,
|
Id: response.Message.Id,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
Object: objectChatCompletionChunk,
|
Object: objectChatCompletionChunk,
|
||||||
Choices: []chatCompletionChoice{choice},
|
Choices: []chatCompletionChoice{choice},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ func (m *hunyuanProvider) convertChunkFromHunyuanToOpenAI(ctx wrapper.HttpContex
|
|||||||
openAIFormattedChunk := &chatCompletionResponse{
|
openAIFormattedChunk := &chatCompletionResponse{
|
||||||
Id: hunyuanFormattedChunk.Id,
|
Id: hunyuanFormattedChunk.Id,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletionChunk,
|
Object: objectChatCompletionChunk,
|
||||||
Usage: usage{
|
Usage: usage{
|
||||||
@@ -470,7 +470,7 @@ func (m *hunyuanProvider) buildChatCompletionResponse(ctx wrapper.HttpContext, h
|
|||||||
return &chatCompletionResponse{
|
return &chatCompletionResponse{
|
||||||
Id: hunyuanResponse.Response.Id,
|
Id: hunyuanResponse.Response.Id,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletion,
|
Object: objectChatCompletion,
|
||||||
Choices: choices,
|
Choices: choices,
|
||||||
|
|||||||
@@ -222,9 +222,9 @@ func (m *minimaxProvider) OnResponseHeaders(ctx wrapper.HttpContext, apiName Api
|
|||||||
return types.ActionContinue, nil
|
return types.ActionContinue, nil
|
||||||
}
|
}
|
||||||
// 模型对应接口为ChatCompletion v2,跳过OnStreamingResponseBody()和OnResponseBody()
|
// 模型对应接口为ChatCompletion v2,跳过OnStreamingResponseBody()和OnResponseBody()
|
||||||
model := ctx.GetContext(ctxKeyFinalRequestModel)
|
model := ctx.GetStringContext(ctxKeyFinalRequestModel, "")
|
||||||
if model != nil {
|
if model != "" {
|
||||||
_, ok := chatCompletionProModels[model.(string)]
|
_, ok := chatCompletionProModels[model]
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.DontReadResponseBody()
|
ctx.DontReadResponseBody()
|
||||||
return types.ActionContinue, nil
|
return types.ActionContinue, nil
|
||||||
|
|||||||
@@ -229,10 +229,7 @@ func (m *qwenProvider) OnStreamingResponseBody(ctx wrapper.HttpContext, name Api
|
|||||||
receivedBody = append(bufferedStreamingBody, chunk...)
|
receivedBody = append(bufferedStreamingBody, chunk...)
|
||||||
}
|
}
|
||||||
|
|
||||||
incrementalStreaming, err := ctx.GetContext(ctxKeyIncrementalStreaming).(bool)
|
incrementalStreaming := ctx.GetBoolContext(ctxKeyIncrementalStreaming, false)
|
||||||
if !err {
|
|
||||||
incrementalStreaming = false
|
|
||||||
}
|
|
||||||
|
|
||||||
eventStartIndex, lineStartIndex, valueStartIndex := -1, -1, -1
|
eventStartIndex, lineStartIndex, valueStartIndex := -1, -1, -1
|
||||||
|
|
||||||
@@ -387,7 +384,7 @@ func (m *qwenProvider) buildChatCompletionResponse(ctx wrapper.HttpContext, qwen
|
|||||||
return &chatCompletionResponse{
|
return &chatCompletionResponse{
|
||||||
Id: qwenResponse.RequestId,
|
Id: qwenResponse.RequestId,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletion,
|
Object: objectChatCompletion,
|
||||||
Choices: choices,
|
Choices: choices,
|
||||||
@@ -403,7 +400,7 @@ func (m *qwenProvider) buildChatCompletionStreamingResponse(ctx wrapper.HttpCont
|
|||||||
baseMessage := chatCompletionResponse{
|
baseMessage := chatCompletionResponse{
|
||||||
Id: qwenResponse.RequestId,
|
Id: qwenResponse.RequestId,
|
||||||
Created: time.Now().UnixMilli() / 1000,
|
Created: time.Now().UnixMilli() / 1000,
|
||||||
Model: ctx.GetContext(ctxKeyFinalRequestModel).(string),
|
Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""),
|
||||||
Choices: make([]chatCompletionChoice, 0),
|
Choices: make([]chatCompletionChoice, 0),
|
||||||
SystemFingerprint: "",
|
SystemFingerprint: "",
|
||||||
Object: objectChatCompletionChunk,
|
Object: objectChatCompletionChunk,
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ type HttpContext interface {
|
|||||||
Method() string
|
Method() string
|
||||||
SetContext(key string, value interface{})
|
SetContext(key string, value interface{})
|
||||||
GetContext(key string) interface{}
|
GetContext(key string) interface{}
|
||||||
|
GetBoolContext(key string, defaultValue bool) bool
|
||||||
|
GetStringContext(key, defaultValue string) string
|
||||||
// If the onHttpRequestBody handle is not set, the request body will not be read by default
|
// If the onHttpRequestBody handle is not set, the request body will not be read by default
|
||||||
DontReadRequestBody()
|
DontReadRequestBody()
|
||||||
// If the onHttpResponseBody handle is not set, the request body will not be read by default
|
// If the onHttpResponseBody handle is not set, the request body will not be read by default
|
||||||
@@ -297,6 +299,20 @@ func (ctx *CommonHttpCtx[PluginConfig]) GetContext(key string) interface{} {
|
|||||||
return ctx.userContext[key]
|
return ctx.userContext[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *CommonHttpCtx[PluginConfig]) GetBoolContext(key string, defaultValue bool) bool {
|
||||||
|
if b, ok := ctx.userContext[key].(bool); ok {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *CommonHttpCtx[PluginConfig]) GetStringContext(key, defaultValue string) string {
|
||||||
|
if s, ok := ctx.userContext[key].(string); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
func (ctx *CommonHttpCtx[PluginConfig]) Scheme() string {
|
func (ctx *CommonHttpCtx[PluginConfig]) Scheme() string {
|
||||||
proxywasm.SetEffectiveContext(ctx.contextID)
|
proxywasm.SetEffectiveContext(ctx.contextID)
|
||||||
return GetRequestScheme()
|
return GetRequestScheme()
|
||||||
|
|||||||
Reference in New Issue
Block a user