mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
Merge pull request #4180 from jianjianai/fix/openai-request-view-single-scan
fix(openai): avoid repeated request body scans
This commit is contained in:
@@ -365,15 +365,57 @@ 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()),
|
||||
}
|
||||
|
||||
const (
|
||||
modelField uint8 = 1 << iota
|
||||
streamField
|
||||
promptCacheKeyField
|
||||
previousResponseIDField
|
||||
serviceTierField
|
||||
reasoningField
|
||||
allRequestViewFields = modelField | streamField | promptCacheKeyField |
|
||||
previousResponseIDField | serviceTierField | reasoningField
|
||||
)
|
||||
|
||||
view := openAIRequestView{body: body}
|
||||
var seen uint8
|
||||
// parseRawJSONView reads body without copying; view keeps body alive for extracted strings.
|
||||
parseRawJSONView(body).ForEach(func(key, value gjson.Result) bool {
|
||||
switch key.Str {
|
||||
case "model":
|
||||
if seen&modelField == 0 {
|
||||
view.Model = strings.TrimSpace(value.String())
|
||||
seen |= modelField
|
||||
}
|
||||
case "stream":
|
||||
if seen&streamField == 0 {
|
||||
view.Stream = value.Bool()
|
||||
seen |= streamField
|
||||
}
|
||||
case "prompt_cache_key":
|
||||
if seen&promptCacheKeyField == 0 {
|
||||
view.PromptCacheKey = strings.TrimSpace(value.String())
|
||||
seen |= promptCacheKeyField
|
||||
}
|
||||
case "previous_response_id":
|
||||
if seen&previousResponseIDField == 0 {
|
||||
view.PreviousResponseID = strings.TrimSpace(value.String())
|
||||
seen |= previousResponseIDField
|
||||
}
|
||||
case "service_tier":
|
||||
if seen&serviceTierField == 0 {
|
||||
view.ServiceTier = strings.TrimSpace(value.String())
|
||||
seen |= serviceTierField
|
||||
}
|
||||
case "reasoning":
|
||||
if seen&reasoningField == 0 {
|
||||
view.ReasoningEffort = strings.TrimSpace(value.Get("effort").String())
|
||||
seen |= reasoningField
|
||||
}
|
||||
}
|
||||
return seen != allRequestViewFields
|
||||
})
|
||||
return view
|
||||
}
|
||||
|
||||
// Decode 保留阶段一既有 full-map 行为;后续阶段会把调用点下沉到复杂分支。
|
||||
|
||||
@@ -27,6 +27,33 @@ func TestOpenAIRequestView_ExtractsRawScalars(t *testing.T) {
|
||||
require.Equal(t, "medium", view.ReasoningEffort)
|
||||
}
|
||||
|
||||
func TestOpenAIRequestView_ExtractsFieldsAfterLargeInput(t *testing.T) {
|
||||
body := []byte(`{"model":"gpt-5","input":[{"content":"` + strings.Repeat("payload", 1024) + `"}],"stream":true,"prompt_cache_key":"session-1","previous_response_id":"resp-1","service_tier":"flex","reasoning":{"effort":"high"}}`)
|
||||
|
||||
view := newOpenAIRequestView(body)
|
||||
|
||||
require.Equal(t, "gpt-5", view.Model)
|
||||
require.True(t, view.Stream)
|
||||
require.Equal(t, "session-1", view.PromptCacheKey)
|
||||
require.Equal(t, "resp-1", view.PreviousResponseID)
|
||||
require.Equal(t, "flex", view.ServiceTier)
|
||||
require.Equal(t, "high", view.ReasoningEffort)
|
||||
}
|
||||
|
||||
func TestOpenAIRequestView_KeepsFirstDuplicateField(t *testing.T) {
|
||||
view := newOpenAIRequestView([]byte(`{"model":"gpt-5","model":"gpt-5.1","reasoning":{"effort":"low"},"reasoning":{"effort":"high"}}`))
|
||||
|
||||
require.Equal(t, "gpt-5", view.Model)
|
||||
require.Equal(t, "low", view.ReasoningEffort)
|
||||
}
|
||||
|
||||
func TestOpenAIRequestView_KeepsLenientPrefixExtraction(t *testing.T) {
|
||||
view := newOpenAIRequestView([]byte(`{"model":"gpt-5","stream":true,"input":[`))
|
||||
|
||||
require.Equal(t, "gpt-5", view.Model)
|
||||
require.True(t, view.Stream)
|
||||
}
|
||||
|
||||
func TestOpenAIRequestView_DecodeKeepsFullMapBehavior(t *testing.T) {
|
||||
view := newOpenAIRequestView([]byte(`{"model":"gpt-5","stream":true,"input":[{"type":"message","content":"hi"}]}`))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user