Skip to content

fix(video): avoid duplicate CORS headers in content proxy - #6576

Open
AmPlace wants to merge 2 commits into
QuantumNous:mainfrom
AmPlace:fix/video-proxy-cors-headers
Open

fix(video): avoid duplicate CORS headers in content proxy#6576
AmPlace wants to merge 2 commits into
QuantumNous:mainfrom
AmPlace:fix/video-proxy-cors-headers

Conversation

@AmPlace

@AmPlace AmPlace commented Jul 31, 2026

Copy link
Copy Markdown

📝 变更描述 / Description

视频内容代理目前会使用 Header().Add() 复制上游的所有响应头。当上游也返回 CORS 响应头时,它们会与当前实例 CORS 中间件已经设置的响应头叠加,导致浏览器因多个 Access-Control-Allow-Origin 值而拒绝读取视频响应。

本次修改在复制视频响应头时跳过上游的所有 Access-Control-* 头,继续由当前实例的 CORS 中间件统一管理;其他响应头(包括普通多值头)保持原有透传行为。新增单元测试覆盖上述行为。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix)
  • ✨ 新功能 (New feature)
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 已结合实际响应头、现有 CORS 中间件和视频代理代码整理此描述。
  • 非重复提交: 已搜索现有 Issues 与 PRs,未发现相同问题。
  • Bug fix 说明: 已提交并关联 Issue 视频内容代理追加上游 CORS 头导致浏览器拒绝响应 #6574
  • 变更理解: 已确认重复响应头来自视频代理对上游 CORS 头的追加。
  • 范围聚焦: 仅修改视频代理响应头复制逻辑并新增对应测试。
  • 本地验证: 已运行并通过 controller 包测试。
  • 安全合规: 代码和测试不包含敏感凭据。

📸 运行证明 / Proof of Work

$ go test ./controller -count=1
ok  github.com/QuantumNous/new-api/controller  0.744s

新增测试验证:

  • 保留当前实例已经设置的 Access-Control-Allow-Origin
  • 不复制上游 Access-Control-* 响应头
  • 正常复制 Content-Type
  • 保留普通响应头的多个值

Summary by CodeRabbit

  • Bug Fixes
    • Improved video proxy responses by preventing upstream CORS headers from overriding the application’s CORS settings.
    • Preserved other upstream response headers, including headers with multiple values.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The video proxy copies upstream response headers through a helper that excludes case-insensitive Access-Control-* headers. Tests verify that existing CORS headers remain unchanged and other header values are preserved.

Changes

Video proxy response header filtering

Layer / File(s) Summary
Filter and validate upstream response headers
controller/video_proxy.go, controller/video_proxy_test.go
The proxy skips upstream Access-Control-* headers and copies other header values. Tests verify CORS preservation and single- and multi-valued non-CORS headers.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I’m a rabbit guarding the stream,
CORS headers stay with their team.
Other values hop through,
In singles and multiples too,
The proxy keeps responses clean.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #6574 by filtering upstream Access-Control-* headers while preserving CORS middleware values and other multi-value headers.
Out of Scope Changes check ✅ Passed The code and test changes are limited to video proxy header filtering and directly support issue #6574.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing duplicate CORS headers in the video content proxy.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
controller/video_proxy_test.go (1)

12-16: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a mixed-case CORS regression case.

All source keys currently use canonical casing. A future case-sensitive filter would still pass this test. Change one Access-Control-* source key to mixed case and keep the existing assertion.

Proposed regression input
 	src := http.Header{
-		"Access-Control-Allow-Origin":  {"https://upstream.example"},
+		"aCcEsS-cOnTrOl-AlLoW-OrIgIn": {"https://upstream.example"},
 		"Access-Control-Allow-Headers": {"Authorization"},

As per coding guidelines, backend tests must protect regression paths. The PR objective requires case-insensitive filtering for every Access-Control-* header.

🤖 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 `@controller/video_proxy_test.go` around lines 12 - 16, Update the src header
fixture in the video proxy test to use mixed casing for one Access-Control-*
key, while preserving its value and all existing assertions. Ensure the test
continues covering case-insensitive filtering for Access-Control-* headers
without changing unrelated headers.

Source: Coding guidelines

🤖 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 `@controller/video_proxy_test.go`:
- Around line 3-7: Update the tests in controller/video_proxy_test.go to replace
reflect.DeepEqual checks with testify/assert and replace t.Fatalf with
testify/require for setup or assertions that must stop execution. Add the
appropriate testify imports and preserve the existing test behavior.

---

Nitpick comments:
In `@controller/video_proxy_test.go`:
- Around line 12-16: Update the src header fixture in the video proxy test to
use mixed casing for one Access-Control-* key, while preserving its value and
all existing assertions. Ensure the test continues covering case-insensitive
filtering for Access-Control-* headers without changing unrelated 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: 2ded9641-3b95-4c54-bc2a-417a10486cb0

📥 Commits

Reviewing files that changed from the base of the PR and between df43f80 and 62313d7.

📒 Files selected for processing (2)
  • controller/video_proxy.go
  • controller/video_proxy_test.go

Comment on lines +3 to +7
import (
"net/http"
"reflect"
"testing"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use the repository assertion packages in this backend test.

The test uses reflect.DeepEqual and t.Fatalf. Replace these checks with testify/assert. Use testify/require for any setup or assertion that must stop the test.

Proposed assertion update
 import (
 	"net/http"
-	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
...
-	if got := dst.Values("Access-Control-Allow-Origin"); !reflect.DeepEqual(got, []string{"*"}) {
-		t.Fatalf("Access-Control-Allow-Origin = %v, want existing middleware value", got)
-	}
+	assert.Equal(t, []string{"*"}, dst.Values("Access-Control-Allow-Origin"))
...
-	if got := dst.Values("Access-Control-Allow-Headers"); len(got) != 0 {
-		t.Fatalf("Access-Control-Allow-Headers = %v, want no copied upstream values", got)
-	}
+	assert.Empty(t, dst.Values("Access-Control-Allow-Headers"))
...
-	if got := dst.Get("Content-Type"); got != "video/mp4" {
-		t.Fatalf("Content-Type = %q, want video/mp4", got)
-	}
+	assert.Equal(t, "video/mp4", dst.Get("Content-Type"))
...
-	if got := dst.Values("X-Upstream-Value"); !reflect.DeepEqual(got, []string{"first", "second"}) {
-		t.Fatalf("X-Upstream-Value = %v, want both upstream values", got)
-	}
+	assert.Equal(t, []string{"first", "second"}, dst.Values("X-Upstream-Value"))

As per coding guidelines, new Go backend tests must use testify/require for setup and fatal assertions and testify/assert for non-fatal checks.

Also applies to: 21-31

🤖 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 `@controller/video_proxy_test.go` around lines 3 - 7, Update the tests in
controller/video_proxy_test.go to replace reflect.DeepEqual checks with
testify/assert and replace t.Fatalf with testify/require for setup or assertions
that must stop execution. Add the appropriate testify imports and preserve the
existing test behavior.

Source: Coding guidelines

@AmPlace
AmPlace marked this pull request as ready for review August 1, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

视频内容代理追加上游 CORS 头导致浏览器拒绝响应

1 participant