Commit a955d410 by Seefs

refactor(override): simplify header overrides to a lowercase single map

parent 3034fb88
...@@ -179,7 +179,7 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s ...@@ -179,7 +179,7 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s
var passthroughRegex []*regexp.Regexp var passthroughRegex []*regexp.Regexp
if !info.IsChannelTest { if !info.IsChannelTest {
for k := range headerOverrideSource { for k := range headerOverrideSource {
key := strings.TrimSpace(k) key := strings.TrimSpace(strings.ToLower(k))
if key == "" { if key == "" {
continue continue
} }
...@@ -188,12 +188,11 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s ...@@ -188,12 +188,11 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s
continue continue
} }
lower := strings.ToLower(key)
var pattern string var pattern string
switch { switch {
case strings.HasPrefix(lower, headerPassthroughRegexPrefix): case strings.HasPrefix(key, headerPassthroughRegexPrefix):
pattern = strings.TrimSpace(key[len(headerPassthroughRegexPrefix):]) pattern = strings.TrimSpace(key[len(headerPassthroughRegexPrefix):])
case strings.HasPrefix(lower, headerPassthroughRegexPrefixV2): case strings.HasPrefix(key, headerPassthroughRegexPrefixV2):
pattern = strings.TrimSpace(key[len(headerPassthroughRegexPrefixV2):]) pattern = strings.TrimSpace(key[len(headerPassthroughRegexPrefixV2):])
default: default:
continue continue
...@@ -234,7 +233,7 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s ...@@ -234,7 +233,7 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s
if value == "" { if value == "" {
continue continue
} }
headerOverride[name] = value headerOverride[strings.ToLower(strings.TrimSpace(name))] = value
} }
} }
...@@ -242,7 +241,7 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s ...@@ -242,7 +241,7 @@ func processHeaderOverride(info *common.RelayInfo, c *gin.Context) (map[string]s
if isHeaderPassthroughRuleKey(k) { if isHeaderPassthroughRuleKey(k) {
continue continue
} }
key := strings.TrimSpace(k) key := strings.TrimSpace(strings.ToLower(k))
if key == "" { if key == "" {
continue continue
} }
......
...@@ -53,7 +53,7 @@ func TestProcessHeaderOverride_ChannelTestSkipsClientHeaderPlaceholder(t *testin ...@@ -53,7 +53,7 @@ func TestProcessHeaderOverride_ChannelTestSkipsClientHeaderPlaceholder(t *testin
headers, err := processHeaderOverride(info, ctx) headers, err := processHeaderOverride(info, ctx)
require.NoError(t, err) require.NoError(t, err)
_, ok := headers["X-Upstream-Trace"] _, ok := headers["x-upstream-trace"]
require.False(t, ok) require.False(t, ok)
} }
...@@ -77,10 +77,10 @@ func TestProcessHeaderOverride_NonTestKeepsClientHeaderPlaceholder(t *testing.T) ...@@ -77,10 +77,10 @@ func TestProcessHeaderOverride_NonTestKeepsClientHeaderPlaceholder(t *testing.T)
headers, err := processHeaderOverride(info, ctx) headers, err := processHeaderOverride(info, ctx)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "trace-123", headers["X-Upstream-Trace"]) require.Equal(t, "trace-123", headers["x-upstream-trace"])
} }
func TestProcessHeaderOverride_RuntimeOverrideMergesWithChannelOverride(t *testing.T) { func TestProcessHeaderOverride_RuntimeOverrideIsFinalHeaderMap(t *testing.T) {
t.Parallel() t.Parallel()
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
...@@ -92,8 +92,8 @@ func TestProcessHeaderOverride_RuntimeOverrideMergesWithChannelOverride(t *testi ...@@ -92,8 +92,8 @@ func TestProcessHeaderOverride_RuntimeOverrideMergesWithChannelOverride(t *testi
IsChannelTest: false, IsChannelTest: false,
UseRuntimeHeadersOverride: true, UseRuntimeHeadersOverride: true,
RuntimeHeadersOverride: map[string]any{ RuntimeHeadersOverride: map[string]any{
"X-Static": "runtime-value", "x-static": "runtime-value",
"X-Runtime": "runtime-only", "x-runtime": "runtime-only",
}, },
ChannelMeta: &relaycommon.ChannelMeta{ ChannelMeta: &relaycommon.ChannelMeta{
HeadersOverride: map[string]any{ HeadersOverride: map[string]any{
...@@ -105,9 +105,10 @@ func TestProcessHeaderOverride_RuntimeOverrideMergesWithChannelOverride(t *testi ...@@ -105,9 +105,10 @@ func TestProcessHeaderOverride_RuntimeOverrideMergesWithChannelOverride(t *testi
headers, err := processHeaderOverride(info, ctx) headers, err := processHeaderOverride(info, ctx)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "runtime-value", headers["X-Static"]) require.Equal(t, "runtime-value", headers["x-static"])
require.Equal(t, "runtime-only", headers["X-Runtime"]) require.Equal(t, "runtime-only", headers["x-runtime"])
require.Equal(t, "legacy-only", headers["X-Legacy"]) _, exists := headers["x-legacy"]
require.False(t, exists)
} }
func TestProcessHeaderOverride_PassthroughSkipsAcceptEncoding(t *testing.T) { func TestProcessHeaderOverride_PassthroughSkipsAcceptEncoding(t *testing.T) {
...@@ -131,9 +132,9 @@ func TestProcessHeaderOverride_PassthroughSkipsAcceptEncoding(t *testing.T) { ...@@ -131,9 +132,9 @@ func TestProcessHeaderOverride_PassthroughSkipsAcceptEncoding(t *testing.T) {
headers, err := processHeaderOverride(info, ctx) headers, err := processHeaderOverride(info, ctx)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "trace-123", headers["X-Trace-Id"]) require.Equal(t, "trace-123", headers["x-trace-id"])
_, hasAcceptEncoding := headers["Accept-Encoding"] _, hasAcceptEncoding := headers["accept-encoding"]
require.False(t, hasAcceptEncoding) require.False(t, hasAcceptEncoding)
} }
...@@ -171,16 +172,17 @@ func TestProcessHeaderOverride_PassHeadersTemplateSetsRuntimeHeaders(t *testing. ...@@ -171,16 +172,17 @@ func TestProcessHeaderOverride_PassHeadersTemplateSetsRuntimeHeaders(t *testing.
_, err := relaycommon.ApplyParamOverrideWithRelayInfo([]byte(`{"model":"gpt-4.1"}`), info) _, err := relaycommon.ApplyParamOverrideWithRelayInfo([]byte(`{"model":"gpt-4.1"}`), info)
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.UseRuntimeHeadersOverride) require.True(t, info.UseRuntimeHeadersOverride)
require.Equal(t, "Codex CLI", info.RuntimeHeadersOverride["Originator"]) require.Equal(t, "Codex CLI", info.RuntimeHeadersOverride["originator"])
require.Equal(t, "sess-123", info.RuntimeHeadersOverride["Session_id"]) require.Equal(t, "sess-123", info.RuntimeHeadersOverride["session_id"])
_, exists := info.RuntimeHeadersOverride["X-Codex-Beta-Features"] _, exists := info.RuntimeHeadersOverride["x-codex-beta-features"]
require.False(t, exists) require.False(t, exists)
require.Equal(t, "legacy-value", info.RuntimeHeadersOverride["x-static"])
headers, err := processHeaderOverride(info, ctx) headers, err := processHeaderOverride(info, ctx)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "Codex CLI", headers["Originator"]) require.Equal(t, "Codex CLI", headers["originator"])
require.Equal(t, "sess-123", headers["Session_id"]) require.Equal(t, "sess-123", headers["session_id"])
_, exists = headers["X-Codex-Beta-Features"] _, exists = headers["x-codex-beta-features"]
require.False(t, exists) require.False(t, exists)
upstreamReq := httptest.NewRequest(http.MethodPost, "https://example.com/v1/responses", nil) upstreamReq := httptest.NewRequest(http.MethodPost, "https://example.com/v1/responses", nil)
......
...@@ -1005,7 +1005,7 @@ func TestApplyParamOverrideSetHeaderAndUseInLaterCondition(t *testing.T) { ...@@ -1005,7 +1005,7 @@ func TestApplyParamOverrideSetHeaderAndUseInLaterCondition(t *testing.T) {
"value": 0.1, "value": 0.1,
"conditions": []interface{}{ "conditions": []interface{}{
map[string]interface{}{ map[string]interface{}{
"path": "header_override_normalized.x_debug_mode", "path": "header_override.x-debug-mode",
"mode": "full", "mode": "full",
"value": "enabled", "value": "enabled",
}, },
...@@ -1036,7 +1036,7 @@ func TestApplyParamOverrideCopyHeaderFromRequestHeaders(t *testing.T) { ...@@ -1036,7 +1036,7 @@ func TestApplyParamOverrideCopyHeaderFromRequestHeaders(t *testing.T) {
"value": 0.1, "value": 0.1,
"conditions": []interface{}{ "conditions": []interface{}{
map[string]interface{}{ map[string]interface{}{
"path": "header_override_normalized.x_upstream_auth", "path": "header_override.x-upstream-auth",
"mode": "contains", "mode": "contains",
"value": "Bearer ", "value": "Bearer ",
}, },
...@@ -1045,9 +1045,6 @@ func TestApplyParamOverrideCopyHeaderFromRequestHeaders(t *testing.T) { ...@@ -1045,9 +1045,6 @@ func TestApplyParamOverrideCopyHeaderFromRequestHeaders(t *testing.T) {
}, },
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"request_headers_raw": map[string]interface{}{
"Authorization": "Bearer token-123",
},
"request_headers": map[string]interface{}{ "request_headers": map[string]interface{}{
"authorization": "Bearer token-123", "authorization": "Bearer token-123",
}, },
...@@ -1071,9 +1068,6 @@ func TestApplyParamOverridePassHeadersSkipsMissingHeaders(t *testing.T) { ...@@ -1071,9 +1068,6 @@ func TestApplyParamOverridePassHeadersSkipsMissingHeaders(t *testing.T) {
}, },
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"request_headers_raw": map[string]interface{}{
"Session_id": "sess-123",
},
"request_headers": map[string]interface{}{ "request_headers": map[string]interface{}{
"session_id": "sess-123", "session_id": "sess-123",
}, },
...@@ -1089,10 +1083,10 @@ func TestApplyParamOverridePassHeadersSkipsMissingHeaders(t *testing.T) { ...@@ -1089,10 +1083,10 @@ func TestApplyParamOverridePassHeadersSkipsMissingHeaders(t *testing.T) {
if !ok { if !ok {
t.Fatalf("expected header_override context map") t.Fatalf("expected header_override context map")
} }
if headers["Session_id"] != "sess-123" { if headers["session_id"] != "sess-123" {
t.Fatalf("expected Session_id to be passed, got: %v", headers["Session_id"]) t.Fatalf("expected session_id to be passed, got: %v", headers["session_id"])
} }
if _, exists := headers["X-Codex-Beta-Features"]; exists { if _, exists := headers["x-codex-beta-features"]; exists {
t.Fatalf("expected missing header to be skipped") t.Fatalf("expected missing header to be skipped")
} }
} }
...@@ -1109,9 +1103,6 @@ func TestApplyParamOverrideCopyHeaderSkipsMissingSource(t *testing.T) { ...@@ -1109,9 +1103,6 @@ func TestApplyParamOverrideCopyHeaderSkipsMissingSource(t *testing.T) {
}, },
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"request_headers_raw": map[string]interface{}{
"Authorization": "Bearer token-123",
},
"request_headers": map[string]interface{}{ "request_headers": map[string]interface{}{
"authorization": "Bearer token-123", "authorization": "Bearer token-123",
}, },
...@@ -1127,7 +1118,7 @@ func TestApplyParamOverrideCopyHeaderSkipsMissingSource(t *testing.T) { ...@@ -1127,7 +1118,7 @@ func TestApplyParamOverrideCopyHeaderSkipsMissingSource(t *testing.T) {
if !ok { if !ok {
return return
} }
if _, exists := headers["X-Upstream-Auth"]; exists { if _, exists := headers["x-upstream-auth"]; exists {
t.Fatalf("expected X-Upstream-Auth to be skipped when source header is missing") t.Fatalf("expected X-Upstream-Auth to be skipped when source header is missing")
} }
} }
...@@ -1144,9 +1135,6 @@ func TestApplyParamOverrideMoveHeaderSkipsMissingSource(t *testing.T) { ...@@ -1144,9 +1135,6 @@ func TestApplyParamOverrideMoveHeaderSkipsMissingSource(t *testing.T) {
}, },
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"request_headers_raw": map[string]interface{}{
"Authorization": "Bearer token-123",
},
"request_headers": map[string]interface{}{ "request_headers": map[string]interface{}{
"authorization": "Bearer token-123", "authorization": "Bearer token-123",
}, },
...@@ -1162,7 +1150,7 @@ func TestApplyParamOverrideMoveHeaderSkipsMissingSource(t *testing.T) { ...@@ -1162,7 +1150,7 @@ func TestApplyParamOverrideMoveHeaderSkipsMissingSource(t *testing.T) {
if !ok { if !ok {
return return
} }
if _, exists := headers["X-Upstream-Auth"]; exists { if _, exists := headers["x-upstream-auth"]; exists {
t.Fatalf("expected X-Upstream-Auth to be skipped when source header is missing") t.Fatalf("expected X-Upstream-Auth to be skipped when source header is missing")
} }
} }
...@@ -1179,9 +1167,6 @@ func TestApplyParamOverrideSyncFieldsHeaderToJSON(t *testing.T) { ...@@ -1179,9 +1167,6 @@ func TestApplyParamOverrideSyncFieldsHeaderToJSON(t *testing.T) {
}, },
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"request_headers_raw": map[string]interface{}{
"session_id": "sess-123",
},
"request_headers": map[string]interface{}{ "request_headers": map[string]interface{}{
"session_id": "sess-123", "session_id": "sess-123",
}, },
...@@ -1234,9 +1219,6 @@ func TestApplyParamOverrideSyncFieldsNoChangeWhenBothExist(t *testing.T) { ...@@ -1234,9 +1219,6 @@ func TestApplyParamOverrideSyncFieldsNoChangeWhenBothExist(t *testing.T) {
}, },
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"request_headers_raw": map[string]interface{}{
"session_id": "cache-header",
},
"request_headers": map[string]interface{}{ "request_headers": map[string]interface{}{
"session_id": "cache-header", "session_id": "cache-header",
}, },
...@@ -1288,10 +1270,7 @@ func TestApplyParamOverrideSetHeaderKeepOrigin(t *testing.T) { ...@@ -1288,10 +1270,7 @@ func TestApplyParamOverrideSetHeaderKeepOrigin(t *testing.T) {
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"header_override": map[string]interface{}{ "header_override": map[string]interface{}{
"X-Feature-Flag": "legacy-value", "x-feature-flag": "legacy-value",
},
"header_override_normalized": map[string]interface{}{
"x_feature_flag": "legacy-value",
}, },
} }
...@@ -1303,8 +1282,8 @@ func TestApplyParamOverrideSetHeaderKeepOrigin(t *testing.T) { ...@@ -1303,8 +1282,8 @@ func TestApplyParamOverrideSetHeaderKeepOrigin(t *testing.T) {
if !ok { if !ok {
t.Fatalf("expected header_override context map") t.Fatalf("expected header_override context map")
} }
if headers["X-Feature-Flag"] != "legacy-value" { if headers["x-feature-flag"] != "legacy-value" {
t.Fatalf("expected keep_origin to preserve old value, got: %v", headers["X-Feature-Flag"]) t.Fatalf("expected keep_origin to preserve old value, got: %v", headers["x-feature-flag"])
} }
} }
...@@ -1371,14 +1350,14 @@ func TestApplyParamOverrideWithRelayInfoSyncRuntimeHeaders(t *testing.T) { ...@@ -1371,14 +1350,14 @@ func TestApplyParamOverrideWithRelayInfoSyncRuntimeHeaders(t *testing.T) {
if !info.UseRuntimeHeadersOverride { if !info.UseRuntimeHeadersOverride {
t.Fatalf("expected runtime header override to be enabled") t.Fatalf("expected runtime header override to be enabled")
} }
if info.RuntimeHeadersOverride["X-Keep-Me"] != "keep" { if info.RuntimeHeadersOverride["x-keep-me"] != "keep" {
t.Fatalf("expected X-Keep-Me header to be preserved, got: %v", info.RuntimeHeadersOverride["X-Keep-Me"]) t.Fatalf("expected x-keep-me header to be preserved, got: %v", info.RuntimeHeadersOverride["x-keep-me"])
} }
if info.RuntimeHeadersOverride["X-Injected-By-Param-Override"] != "enabled" { if info.RuntimeHeadersOverride["x-injected-by-param-override"] != "enabled" {
t.Fatalf("expected X-Injected-By-Param-Override header to be set, got: %v", info.RuntimeHeadersOverride["X-Injected-By-Param-Override"]) t.Fatalf("expected x-injected-by-param-override header to be set, got: %v", info.RuntimeHeadersOverride["x-injected-by-param-override"])
} }
if _, exists := info.RuntimeHeadersOverride["X-Delete-Me"]; exists { if _, exists := info.RuntimeHeadersOverride["x-delete-me"]; exists {
t.Fatalf("expected X-Delete-Me header to be deleted") t.Fatalf("expected x-delete-me header to be deleted")
} }
} }
...@@ -1410,25 +1389,22 @@ func TestApplyParamOverrideWithRelayInfoMoveAndCopyHeaders(t *testing.T) { ...@@ -1410,25 +1389,22 @@ func TestApplyParamOverrideWithRelayInfoMoveAndCopyHeaders(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("ApplyParamOverrideWithRelayInfo returned error: %v", err) t.Fatalf("ApplyParamOverrideWithRelayInfo returned error: %v", err)
} }
if _, exists := info.RuntimeHeadersOverride["X-Legacy-Trace"]; exists { if _, exists := info.RuntimeHeadersOverride["x-legacy-trace"]; exists {
t.Fatalf("expected source header to be removed after move") t.Fatalf("expected source header to be removed after move")
} }
if info.RuntimeHeadersOverride["X-Trace"] != "trace-123" { if info.RuntimeHeadersOverride["x-trace"] != "trace-123" {
t.Fatalf("expected X-Trace to be set, got: %v", info.RuntimeHeadersOverride["X-Trace"]) t.Fatalf("expected x-trace to be set, got: %v", info.RuntimeHeadersOverride["x-trace"])
} }
if info.RuntimeHeadersOverride["X-Trace-Backup"] != "trace-123" { if info.RuntimeHeadersOverride["x-trace-backup"] != "trace-123" {
t.Fatalf("expected X-Trace-Backup to be copied, got: %v", info.RuntimeHeadersOverride["X-Trace-Backup"]) t.Fatalf("expected x-trace-backup to be copied, got: %v", info.RuntimeHeadersOverride["x-trace-backup"])
} }
} }
func TestGetEffectiveHeaderOverrideMergesRuntimeAndChannelOverrides(t *testing.T) { func TestGetEffectiveHeaderOverrideUsesRuntimeOverrideAsFinalResult(t *testing.T) {
info := &RelayInfo{ info := &RelayInfo{
UseRuntimeHeadersOverride: true, UseRuntimeHeadersOverride: true,
RuntimeHeadersOverride: map[string]interface{}{ RuntimeHeadersOverride: map[string]interface{}{
"X-Runtime": "runtime-only", "x-runtime": "runtime-only",
},
RuntimeHeadersDeletedNormalized: map[string]bool{
"x-deleted": true,
}, },
ChannelMeta: &ChannelMeta{ ChannelMeta: &ChannelMeta{
HeadersOverride: map[string]interface{}{ HeadersOverride: map[string]interface{}{
...@@ -1439,14 +1415,11 @@ func TestGetEffectiveHeaderOverrideMergesRuntimeAndChannelOverrides(t *testing.T ...@@ -1439,14 +1415,11 @@ func TestGetEffectiveHeaderOverrideMergesRuntimeAndChannelOverrides(t *testing.T
} }
effective := GetEffectiveHeaderOverride(info) effective := GetEffectiveHeaderOverride(info)
if effective["X-Static"] != "static-value" { if effective["x-runtime"] != "runtime-only" {
t.Fatalf("expected X-Static from channel override, got: %v", effective["X-Static"]) t.Fatalf("expected x-runtime from runtime override, got: %v", effective["x-runtime"])
}
if effective["X-Runtime"] != "runtime-only" {
t.Fatalf("expected X-Runtime from runtime override, got: %v", effective["X-Runtime"])
} }
if _, exists := effective["X-Deleted"]; exists { if _, exists := effective["x-static"]; exists {
t.Fatalf("expected deleted headers to stay deleted in effective override") t.Fatalf("expected runtime override to be final and not merge channel headers")
} }
} }
......
...@@ -148,7 +148,6 @@ type RelayInfo struct { ...@@ -148,7 +148,6 @@ type RelayInfo struct {
RetryIndex int RetryIndex int
LastError *types.NewAPIError LastError *types.NewAPIError
RuntimeHeadersOverride map[string]interface{} RuntimeHeadersOverride map[string]interface{}
RuntimeHeadersDeletedNormalized map[string]bool
UseRuntimeHeadersOverride bool UseRuntimeHeadersOverride bool
PriceData types.PriceData PriceData types.PriceData
......
package service package service
import ( import (
"fmt"
"net/http"
"net/http/httptest" "net/http/httptest"
"strings"
"testing" "testing"
"time"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -67,3 +73,73 @@ func TestApplyChannelAffinityOverrideTemplate_MergeTemplate(t *testing.T) { ...@@ -67,3 +73,73 @@ func TestApplyChannelAffinityOverrideTemplate_MergeTemplate(t *testing.T) {
require.Equal(t, "rule-with-template", overrideInfo["rule_name"]) require.Equal(t, "rule-with-template", overrideInfo["rule_name"])
require.EqualValues(t, 2, overrideInfo["param_override_keys"]) require.EqualValues(t, 2, overrideInfo["param_override_keys"])
} }
func TestChannelAffinityHitCodexTemplatePassHeadersEffective(t *testing.T) {
gin.SetMode(gin.TestMode)
setting := operation_setting.GetChannelAffinitySetting()
require.NotNil(t, setting)
var codexRule *operation_setting.ChannelAffinityRule
for i := range setting.Rules {
rule := &setting.Rules[i]
if strings.EqualFold(strings.TrimSpace(rule.Name), "codex cli trace") {
codexRule = rule
break
}
}
require.NotNil(t, codexRule)
affinityValue := fmt.Sprintf("pc-hit-%d", time.Now().UnixNano())
cacheKeySuffix := buildChannelAffinityCacheKeySuffix(*codexRule, "default", affinityValue)
cache := getChannelAffinityCache()
require.NoError(t, cache.SetWithTTL(cacheKeySuffix, 9527, time.Minute))
t.Cleanup(func() {
_, _ = cache.DeleteMany([]string{cacheKeySuffix})
})
rec := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(rec)
ctx.Request = httptest.NewRequest(http.MethodPost, "/v1/responses", strings.NewReader(fmt.Sprintf(`{"prompt_cache_key":"%s"}`, affinityValue)))
ctx.Request.Header.Set("Content-Type", "application/json")
channelID, found := GetPreferredChannelByAffinity(ctx, "gpt-5", "default")
require.True(t, found)
require.Equal(t, 9527, channelID)
baseOverride := map[string]interface{}{
"temperature": 0.2,
}
mergedOverride, applied := ApplyChannelAffinityOverrideTemplate(ctx, baseOverride)
require.True(t, applied)
require.Equal(t, 0.2, mergedOverride["temperature"])
info := &relaycommon.RelayInfo{
RequestHeaders: map[string]string{
"Originator": "Codex CLI",
"Session_id": "sess-123",
"User-Agent": "codex-cli-test",
},
ChannelMeta: &relaycommon.ChannelMeta{
ParamOverride: mergedOverride,
HeadersOverride: map[string]interface{}{
"X-Static": "legacy-static",
},
},
}
_, err := relaycommon.ApplyParamOverrideWithRelayInfo([]byte(`{"model":"gpt-5"}`), info)
require.NoError(t, err)
require.True(t, info.UseRuntimeHeadersOverride)
require.Equal(t, "legacy-static", info.RuntimeHeadersOverride["x-static"])
require.Equal(t, "Codex CLI", info.RuntimeHeadersOverride["originator"])
require.Equal(t, "sess-123", info.RuntimeHeadersOverride["session_id"])
require.Equal(t, "codex-cli-test", info.RuntimeHeadersOverride["user-agent"])
_, exists := info.RuntimeHeadersOverride["x-codex-beta-features"]
require.False(t, exists)
_, exists = info.RuntimeHeadersOverride["x-codex-turn-metadata"]
require.False(t, exists)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment