fix(relay): apply channel header override on task API requests - #6595
fix(relay): apply channel header override on task API requests#6595tancheng33 wants to merge 1 commit into
Conversation
Walkthrough
ChangesTask request header overrides
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@relay/channel/api_request_test.go`:
- Around line 205-242: Strengthen TestDoTaskApiRequest_AppliesHeaderOverride by
having headerOverrideTaskAdaptor.BuildRequestHeader set X-Upstream-Token to a
different value before the request is sent, then retain the assertion that the
received header is override-token. This verifies explicit channel overrides take
precedence over adaptor-provided headers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2c7055db-3de4-4adc-83c6-4b0c27cdc4e9
📒 Files selected for processing (2)
relay/channel/api_request.gorelay/channel/api_request_test.go
| func (a *headerOverrideTaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { | ||
| req.Header.Set("Authorization", "Bearer channel-key") | ||
| return nil | ||
| } | ||
|
|
||
| func TestDoTaskApiRequest_AppliesHeaderOverride(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| gin.SetMode(gin.TestMode) | ||
| received := make(chan http.Header, 1) | ||
| upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| received <- r.Header.Clone() | ||
| w.WriteHeader(http.StatusOK) | ||
| })) | ||
| defer upstream.Close() | ||
|
|
||
| recorder := httptest.NewRecorder() | ||
| ctx, _ := gin.CreateTestContext(recorder) | ||
| ctx.Request = httptest.NewRequest(http.MethodPost, "/v1/video/generations", strings.NewReader("{}")) | ||
| ctx.Request.Header.Set("Idempotency-Key", "idem-123") | ||
|
|
||
| info := &relaycommon.RelayInfo{ | ||
| ChannelMeta: &relaycommon.ChannelMeta{ | ||
| HeadersOverride: map[string]any{ | ||
| "*": "", | ||
| "X-Upstream-Token": "override-token", | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| resp, err := DoTaskApiRequest(&headerOverrideTaskAdaptor{upstreamURL: upstream.URL}, ctx, info, strings.NewReader("{}")) | ||
| require.NoError(t, err) | ||
| defer resp.Body.Close() | ||
|
|
||
| headers := <-received | ||
| require.Equal(t, "idem-123", headers.Get("Idempotency-Key")) | ||
| require.Equal(t, "override-token", headers.Get("X-Upstream-Token")) | ||
| require.Equal(t, "Bearer channel-key", headers.Get("Authorization")) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Test explicit override precedence against an adaptor header.
BuildRequestHeader does not set X-Upstream-Token. The test passes even if overrides run before BuildRequestHeader. Set a different X-Upstream-Token value in the adaptor. Then assert that "override-token" replaces it.
Proposed test change
func (a *headerOverrideTaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error {
req.Header.Set("Authorization", "Bearer channel-key")
+ req.Header.Set("X-Upstream-Token", "channel-token")
return nil
}As per coding guidelines, “Backend tests must protect real behavior, API contracts, billing/accounting invariants, compatibility, or regression paths.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func (a *headerOverrideTaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { | |
| req.Header.Set("Authorization", "Bearer channel-key") | |
| return nil | |
| } | |
| func TestDoTaskApiRequest_AppliesHeaderOverride(t *testing.T) { | |
| t.Parallel() | |
| gin.SetMode(gin.TestMode) | |
| received := make(chan http.Header, 1) | |
| upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| received <- r.Header.Clone() | |
| w.WriteHeader(http.StatusOK) | |
| })) | |
| defer upstream.Close() | |
| recorder := httptest.NewRecorder() | |
| ctx, _ := gin.CreateTestContext(recorder) | |
| ctx.Request = httptest.NewRequest(http.MethodPost, "/v1/video/generations", strings.NewReader("{}")) | |
| ctx.Request.Header.Set("Idempotency-Key", "idem-123") | |
| info := &relaycommon.RelayInfo{ | |
| ChannelMeta: &relaycommon.ChannelMeta{ | |
| HeadersOverride: map[string]any{ | |
| "*": "", | |
| "X-Upstream-Token": "override-token", | |
| }, | |
| }, | |
| } | |
| resp, err := DoTaskApiRequest(&headerOverrideTaskAdaptor{upstreamURL: upstream.URL}, ctx, info, strings.NewReader("{}")) | |
| require.NoError(t, err) | |
| defer resp.Body.Close() | |
| headers := <-received | |
| require.Equal(t, "idem-123", headers.Get("Idempotency-Key")) | |
| require.Equal(t, "override-token", headers.Get("X-Upstream-Token")) | |
| require.Equal(t, "Bearer channel-key", headers.Get("Authorization")) | |
| func (a *headerOverrideTaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { | |
| req.Header.Set("Authorization", "Bearer channel-key") | |
| req.Header.Set("X-Upstream-Token", "channel-token") | |
| return nil | |
| } | |
| func TestDoTaskApiRequest_AppliesHeaderOverride(t *testing.T) { | |
| t.Parallel() | |
| gin.SetMode(gin.TestMode) | |
| received := make(chan http.Header, 1) | |
| upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| received <- r.Header.Clone() | |
| w.WriteHeader(http.StatusOK) | |
| })) | |
| defer upstream.Close() | |
| recorder := httptest.NewRecorder() | |
| ctx, _ := gin.CreateTestContext(recorder) | |
| ctx.Request = httptest.NewRequest(http.MethodPost, "/v1/video/generations", strings.NewReader("{}")) | |
| ctx.Request.Header.Set("Idempotency-Key", "idem-123") | |
| info := &relaycommon.RelayInfo{ | |
| ChannelMeta: &relaycommon.ChannelMeta{ | |
| HeadersOverride: map[string]any{ | |
| "*": "", | |
| "X-Upstream-Token": "override-token", | |
| }, | |
| }, | |
| } | |
| resp, err := DoTaskApiRequest(&headerOverrideTaskAdaptor{upstreamURL: upstream.URL}, ctx, info, strings.NewReader("{}")) | |
| require.NoError(t, err) | |
| defer resp.Body.Close() | |
| headers := <-received | |
| require.Equal(t, "idem-123", headers.Get("Idempotency-Key")) | |
| require.Equal(t, "override-token", headers.Get("X-Upstream-Token")) | |
| require.Equal(t, "Bearer channel-key", headers.Get("Authorization")) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@relay/channel/api_request_test.go` around lines 205 - 242, Strengthen
TestDoTaskApiRequest_AppliesHeaderOverride by having
headerOverrideTaskAdaptor.BuildRequestHeader set X-Upstream-Token to a different
value before the request is sent, then retain the assertion that the received
header is override-token. This verifies explicit channel overrides take
precedence over adaptor-provided headers.
Source: Coding guidelines
📝 变更描述 / Description
DoTaskApiRequest(视频/异步任务转发路径)只调用各 TaskAdaptor 的BuildRequestHeader,没有像DoApiRequest/DoWssRequest等同步路径那样应用渠道「请求头覆盖」。因此任务类渠道(如豆包视频)上{"*": true}透传模板和显式覆盖均不生效,客户端的Idempotency-Key等头无法到达上游。修复方式:在
BuildRequestHeader之后按同文件既有模式调用processHeaderOverride+applyHeaderOverrideToRequest,保持「用户设置优先级最高」的一致语义。通配透传仍受既有 skip 名单约束,Authorization等凭据头不会被透传(新增测试覆盖了这一点)。🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。说明:本修复由 AI 辅助完成,已人工审阅代码与测试结果。
📸 运行证明 / Proof of Work
新增测试
TestDoTaskApiRequest_AppliesHeaderOverride:httptest 模拟上游 + stub TaskAdaptor,验证{"*": ""}下客户端Idempotency-Key透传、显式覆盖生效、且渠道Authorization不被通配透传覆盖。Summary by CodeRabbit