mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
refactor(gateway): introduce OpenAI request view
Cache hot-path request scalars before full body decoding so later branches can avoid repeated map work while preserving current decode behavior.
This commit is contained in:
@@ -2346,7 +2346,8 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
|
||||
}
|
||||
|
||||
originalBody := body
|
||||
reqModel, reqStream, promptCacheKey := extractOpenAIRequestMetaFromBody(body)
|
||||
requestView := newOpenAIRequestView(body)
|
||||
reqModel, reqStream, promptCacheKey := requestView.Model, requestView.Stream, requestView.PromptCacheKey
|
||||
originalModel := reqModel
|
||||
|
||||
if account.Type == AccountTypeAPIKey && !openai_compat.ShouldUseResponsesAPI(account.Extra) {
|
||||
@@ -2396,7 +2397,7 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
|
||||
return s.forwardOpenAIPassthrough(ctx, c, account, originalBody, reqModel, reasoningEffort, reqStream, startTime)
|
||||
}
|
||||
|
||||
reqBody, err := getOpenAIRequestBodyMap(c, body)
|
||||
reqBody, err := requestView.Decode(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -6274,15 +6275,39 @@ func deriveOpenAIReasoningEffortFromModel(model string) string {
|
||||
return normalizeOpenAIReasoningEffort(parts[len(parts)-1])
|
||||
}
|
||||
|
||||
func extractOpenAIRequestMetaFromBody(body []byte) (model string, stream bool, promptCacheKey string) {
|
||||
if len(body) == 0 {
|
||||
return "", false, ""
|
||||
}
|
||||
type openAIRequestView struct {
|
||||
body []byte
|
||||
Model string
|
||||
Stream bool
|
||||
PromptCacheKey string
|
||||
PreviousResponseID string
|
||||
ServiceTier string
|
||||
ReasoningEffort string
|
||||
}
|
||||
|
||||
model = strings.TrimSpace(gjson.GetBytes(body, "model").String())
|
||||
stream = gjson.GetBytes(body, "stream").Bool()
|
||||
promptCacheKey = strings.TrimSpace(gjson.GetBytes(body, "prompt_cache_key").String())
|
||||
return model, stream, promptCacheKey
|
||||
func newOpenAIRequestView(body []byte) openAIRequestView {
|
||||
if len(body) == 0 {
|
||||
return openAIRequestView{}
|
||||
}
|
||||
return openAIRequestView{
|
||||
body: body,
|
||||
Model: strings.TrimSpace(gjson.GetBytes(body, "model").String()),
|
||||
Stream: gjson.GetBytes(body, "stream").Bool(),
|
||||
PromptCacheKey: strings.TrimSpace(gjson.GetBytes(body, "prompt_cache_key").String()),
|
||||
PreviousResponseID: strings.TrimSpace(gjson.GetBytes(body, "previous_response_id").String()),
|
||||
ServiceTier: strings.TrimSpace(gjson.GetBytes(body, "service_tier").String()),
|
||||
ReasoningEffort: strings.TrimSpace(gjson.GetBytes(body, "reasoning.effort").String()),
|
||||
}
|
||||
}
|
||||
|
||||
// Decode 保留阶段一既有 full-map 行为;后续阶段会把调用点下沉到复杂分支。
|
||||
func (v openAIRequestView) Decode(c *gin.Context) (map[string]any, error) {
|
||||
return getOpenAIRequestBodyMap(c, v.body)
|
||||
}
|
||||
|
||||
func extractOpenAIRequestMetaFromBody(body []byte) (model string, stream bool, promptCacheKey string) {
|
||||
view := newOpenAIRequestView(body)
|
||||
return view.Model, view.Stream, view.PromptCacheKey
|
||||
}
|
||||
|
||||
// normalizeOpenAIPassthroughOAuthBody 将透传 OAuth 请求体收敛为旧链路关键行为:
|
||||
|
||||
@@ -9,6 +9,26 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestOpenAIRequestView_ExtractsRawScalars(t *testing.T) {
|
||||
view := newOpenAIRequestView([]byte(`{"model":" gpt-5 ","stream":true,"prompt_cache_key":" ses-1 ","previous_response_id":" resp-1 ","service_tier":" fast ","reasoning":{"effort":" medium "}}`))
|
||||
|
||||
require.Equal(t, "gpt-5", view.Model)
|
||||
require.True(t, view.Stream)
|
||||
require.Equal(t, "ses-1", view.PromptCacheKey)
|
||||
require.Equal(t, "resp-1", view.PreviousResponseID)
|
||||
require.Equal(t, "fast", view.ServiceTier)
|
||||
require.Equal(t, "medium", view.ReasoningEffort)
|
||||
}
|
||||
|
||||
func TestOpenAIRequestView_DecodeKeepsFullMapBehavior(t *testing.T) {
|
||||
view := newOpenAIRequestView([]byte(`{"model":"gpt-5","stream":true,"input":[{"type":"message","content":"hi"}]}`))
|
||||
|
||||
reqBody, err := view.Decode(nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "gpt-5", reqBody["model"])
|
||||
require.IsType(t, []any{}, reqBody["input"])
|
||||
}
|
||||
|
||||
func TestExtractOpenAIRequestMetaFromBody(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
Reference in New Issue
Block a user