feat(sync): full code sync from release
This commit is contained in:
@@ -41,7 +41,14 @@ var hopByHopHeaders = map[string]struct{}{
|
||||
"connection": {},
|
||||
}
|
||||
|
||||
func FilterHeaders(src http.Header, cfg config.ResponseHeaderConfig) http.Header {
|
||||
type CompiledHeaderFilter struct {
|
||||
allowed map[string]struct{}
|
||||
forceRemove map[string]struct{}
|
||||
}
|
||||
|
||||
var defaultCompiledHeaderFilter = CompileHeaderFilter(config.ResponseHeaderConfig{})
|
||||
|
||||
func CompileHeaderFilter(cfg config.ResponseHeaderConfig) *CompiledHeaderFilter {
|
||||
allowed := make(map[string]struct{}, len(defaultAllowed)+len(cfg.AdditionalAllowed))
|
||||
for key := range defaultAllowed {
|
||||
allowed[key] = struct{}{}
|
||||
@@ -69,13 +76,24 @@ func FilterHeaders(src http.Header, cfg config.ResponseHeaderConfig) http.Header
|
||||
}
|
||||
}
|
||||
|
||||
return &CompiledHeaderFilter{
|
||||
allowed: allowed,
|
||||
forceRemove: forceRemove,
|
||||
}
|
||||
}
|
||||
|
||||
func FilterHeaders(src http.Header, filter *CompiledHeaderFilter) http.Header {
|
||||
if filter == nil {
|
||||
filter = defaultCompiledHeaderFilter
|
||||
}
|
||||
|
||||
filtered := make(http.Header, len(src))
|
||||
for key, values := range src {
|
||||
lower := strings.ToLower(key)
|
||||
if _, blocked := forceRemove[lower]; blocked {
|
||||
if _, blocked := filter.forceRemove[lower]; blocked {
|
||||
continue
|
||||
}
|
||||
if _, ok := allowed[lower]; !ok {
|
||||
if _, ok := filter.allowed[lower]; !ok {
|
||||
continue
|
||||
}
|
||||
// 跳过 hop-by-hop 头部,这些由 HTTP 库自动处理
|
||||
@@ -89,8 +107,8 @@ func FilterHeaders(src http.Header, cfg config.ResponseHeaderConfig) http.Header
|
||||
return filtered
|
||||
}
|
||||
|
||||
func WriteFilteredHeaders(dst http.Header, src http.Header, cfg config.ResponseHeaderConfig) {
|
||||
filtered := FilterHeaders(src, cfg)
|
||||
func WriteFilteredHeaders(dst http.Header, src http.Header, filter *CompiledHeaderFilter) {
|
||||
filtered := FilterHeaders(src, filter)
|
||||
for key, values := range filtered {
|
||||
for _, value := range values {
|
||||
dst.Add(key, value)
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestFilterHeadersDisabledUsesDefaultAllowlist(t *testing.T) {
|
||||
ForceRemove: []string{"x-request-id"},
|
||||
}
|
||||
|
||||
filtered := FilterHeaders(src, cfg)
|
||||
filtered := FilterHeaders(src, CompileHeaderFilter(cfg))
|
||||
if filtered.Get("Content-Type") != "application/json" {
|
||||
t.Fatalf("expected Content-Type passthrough, got %q", filtered.Get("Content-Type"))
|
||||
}
|
||||
@@ -51,7 +51,7 @@ func TestFilterHeadersEnabledUsesAllowlist(t *testing.T) {
|
||||
ForceRemove: []string{"x-remove"},
|
||||
}
|
||||
|
||||
filtered := FilterHeaders(src, cfg)
|
||||
filtered := FilterHeaders(src, CompileHeaderFilter(cfg))
|
||||
if filtered.Get("Content-Type") != "application/json" {
|
||||
t.Fatalf("expected Content-Type allowed, got %q", filtered.Get("Content-Type"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user