From eec32a0bb5a11651c6a7b04ce82dc50610f2b27e Mon Sep 17 00:00:00 2001 From: Asim Viladi Oglu Manizada <257676403+manizada@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:19:42 -0800 Subject: [PATCH] Merge commit from fork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normalize exact hosts at provisioning and reqHost in the fast path so case-different Host variants can’t bypass host-gated routes. Co-authored-by: Asim Viladi Oglu Manizada --- modules/caddyhttp/matchers.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index afba1b36f..eda8cd3ae 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -262,13 +262,17 @@ func (m MatchHost) Provision(_ caddy.Context) error { if err != nil { return fmt.Errorf("converting hostname '%s' to ASCII: %v", host, err) } - if asciiHost != host { - m[i] = asciiHost - } normalizedHost := strings.ToLower(asciiHost) if firstI, ok := seen[normalizedHost]; ok { return fmt.Errorf("host at index %d is repeated at index %d: %s", firstI, i, host) } + // Normalize exact hosts for standardized comparison in large-list fastpath later on. + // Keep wildcards/placeholders untouched. + if m.fuzzy(asciiHost) { + m[i] = asciiHost + } else { + m[i] = normalizedHost + } seen[normalizedHost] = i } @@ -312,14 +316,15 @@ func (m MatchHost) MatchWithError(r *http.Request) (bool, error) { } if m.large() { + reqHostLower := strings.ToLower(reqHost) // fast path: locate exact match using binary search (about 100-1000x faster for large lists) pos := sort.Search(len(m), func(i int) bool { if m.fuzzy(m[i]) { return false } - return m[i] >= reqHost + return m[i] >= reqHostLower }) - if pos < len(m) && strings.EqualFold(m[pos], reqHost) { + if pos < len(m) && m[pos] == reqHostLower { return true, nil } }