diff --git a/conformance/utils/echo/pod.go b/conformance/utils/echo/pod.go index 8e4dd884ad..fcd04ae29e 100644 --- a/conformance/utils/echo/pod.go +++ b/conformance/utils/echo/pod.go @@ -20,7 +20,6 @@ import ( "bytes" "context" "fmt" - "net" "strings" "testing" "time" @@ -58,7 +57,7 @@ func (m *MeshPod) MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, t.Helper() http.AwaitConvergence(t, timeoutConfig.RequiredConsecutiveSuccesses, timeoutConfig.MaxTimeToConsistency, func(elapsed time.Duration) bool { - req := makeRequest(exp.Request) + req := makeRequest(t, exp.Request) resp, err := m.request(req) if err != nil { @@ -76,12 +75,12 @@ func (m *MeshPod) MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, t.Logf("Request passed") } -func makeRequest(r http.Request) []string { +func makeRequest(t *testing.T, r http.Request) []string { protocol := strings.ToLower(r.Protocol) if protocol == "" { protocol = "http" } - host := calculateHost(r.Host, protocol) + host := http.CalculateHost(t, r.Host, protocol) args := []string{"client", fmt.Sprintf("%s://%s%s", protocol, host, r.Path)} if r.Method != "" { args = append(args, "--method="+r.Method) @@ -113,32 +112,6 @@ func compareRequest(exp http.ExpectedResponse, resp Response) error { return nil } -// copied from conformance/http to get the ipv6 matching -func calculateHost(reqHost, scheme string) string { - host, port, err := net.SplitHostPort(reqHost) - if err != nil { - return reqHost - } - if strings.ToLower(scheme) == "http" && port == "80" { - return ipv6SafeHost(host) - } - if strings.ToLower(scheme) == "https" && port == "443" { - return ipv6SafeHost(host) - } - return reqHost -} - -func ipv6SafeHost(host string) string { - // We assume that host is a literal IPv6 address if host has - // colons. - // Per https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2. - // This is like net.JoinHostPort, but we don't need a port. - if strings.Contains(host, ":") { - return "[" + host + "]" - } - return host -} - func (m *MeshPod) request(args []string) (Response, error) { container := "echo" diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index a86ea48e09..61fbf4eccb 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -112,7 +112,7 @@ func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, sch } path, query, _ := strings.Cut(expected.Request.Path, "?") - reqURL := url.URL{Scheme: scheme, Host: calculateHost(gwAddr, scheme), Path: path, RawQuery: query} + reqURL := url.URL{Scheme: scheme, Host: CalculateHost(t, gwAddr, scheme), Path: path, RawQuery: query} t.Logf("Making %s request to %s", expected.Request.Method, reqURL.String()) @@ -140,14 +140,21 @@ func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, sch return req } -// calculateHost will calculate the Host header as per [HTTP spec]. To +// CalculateHost will calculate the Host header as per [HTTP spec]. To // summarize, host will not include any port if it is implied from the scheme. In // case of any error, the input gwAddr will be returned as the default. // // [HTTP spec]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23 -func calculateHost(gwAddr, scheme string) string { - host, port, err := net.SplitHostPort(gwAddr) +func CalculateHost(t *testing.T, gwAddr, scheme string) string { + host, port, err := net.SplitHostPort(gwAddr) // note: this will strip brackets of an IPv6 address + if err != nil && strings.Contains(err.Error(), "too many colons in address") { + // This is an IPv6 address; assume it's valid ipv6 + // Assume caller won't add a port without brackets + gwAddr = "[" + gwAddr + "]" + host, port, err = net.SplitHostPort(gwAddr) + } if err != nil { + t.Logf("Failed to parse host %q: %v", gwAddr, err) return gwAddr } if strings.ToLower(scheme) == "http" && port == "80" {