Repository navigation
Strip the port from a bracketed IPv6 host correctly - #817
Open
januththedev wants to merge 1 commit into
Open
januththedev wants to merge 1 commit into
januththedev wants to merge 1 commit into
Conversation
januththedev
force-pushed
the
fix/ipv6-host-port
branch
from
October 3, 2026 10:24
3e17031 to
a7e766e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Strip the port from a bracketed IPv6 host correctly
Description
routeRegexp.MatchandrouteRegexpGroup.setMatchboth dropped the port by truncating at the first colon:An IPv6 literal in a
Hostheader is bracketed per RFC 3986 §3.2.2 ([::1]:8080), so the port separator is the colon after the closing bracket — the first colon is inside the address. Truncating at the first colon destroys the host.Why it's wrong — two distinct symptoms
r.Host("{host}")withHost: [::1]:8080setsmux.Vars(req)["host"] == "[". The route still matches (the default pattern[^.]+happily matches"["), so this fails silently with garbage data in the handler rather than 404ing. For a longer literal it is not even one character:[2001:db8::1]:80yields"[2001".r.Host("[{host}]")never matches[::1]. This is made worse by the escaped pattern:wildcardHostPortis computed frompatternStr, and for"[{host}]"that string is^\[(?P<v0>[^.]+)\]$— no colon — so port-stripping is wrongly enabled for a template that never intended it.The fix
The
HasPrefix("[")guard keeps malformed input on the original path, so only valid bracketed literals change behaviour.Tests
TestHostVarWithIPv6— parameterized over[::1],[::1]:8080, and[2001:db8::1]:80, plus two non-IPv6 controls (example:8080,example) that pass both before and after and therefore pin existing behaviour.TestHostMatchIPv6Literal— assertsHost("[{host}]")matches a[::1]request.Before the fix, all three IPv6 var cases failed (
"[","[","[2001") and the literal-template case did not match at all. After: all pass.Pre-existing failures on unmodified HEAD: zero, measured directly and again from a pristine
git archivecopy so the working tree was never disturbed.go test -racecannot run here (gcc: fatal error: cannot execute 'cc1', no C compiler), so CI's exact command is unrunnable locally;gofmtflags every file in the repo including untouched ones because the checkout is CRLF, and I preserved CRLF so the diff has no line-ending churn.I fetched
regexp.gofrommainand both blocks are byte-identical to this HEAD, so this is unfixed upstream. Searches for IPv6 in issues turn up only closed #134 (2018, about ports). I deliberately avoided the areas already claimed: PR #641 (double-escaping withUseEncodedPath) and the semicolon query-separator cluster (#781/#787/#798/#811).route.go:471returning a nil*RoutefromQueries()on an odd arg count (sor.Queries("a").Handler(h)panics instead of surfacing the error) is a real neighbouring defect I left alone to keep this change narrow.