diff --git a/registry/client/auth/addr.go b/registry/client/auth/addr.go new file mode 100644 index 00000000..6e777528 --- /dev/null +++ b/registry/client/auth/addr.go @@ -0,0 +1,27 @@ +package auth + +import ( + "net/url" + "strings" +) + +// FROM: https://golang.org/src/net/http/http.go +// Given a string of the form "host", "host:port", or "[ipv6::address]:port", +// return true if the string includes a port. +func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } + +// FROM: http://golang.org/src/net/http/transport.go +var portMap = map[string]string{ + "http": "80", + "https": "443", +} + +// canonicalAddr returns url.Host but always with a ":port" suffix +// FROM: http://golang.org/src/net/http/transport.go +func canonicalAddr(url *url.URL) string { + addr := url.Host + if !hasPort(addr) { + return addr + ":" + portMap[url.Scheme] + } + return addr +} diff --git a/registry/client/auth/authchallenge.go b/registry/client/auth/authchallenge.go index e8cdef7f..69d9d6fe 100644 --- a/registry/client/auth/authchallenge.go +++ b/registry/client/auth/authchallenge.go @@ -54,8 +54,13 @@ type simpleChallengeManager struct { Challanges map[string][]Challenge } -func (m *simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { +func normalizeURL(endpoint *url.URL) { endpoint.Host = strings.ToLower(endpoint.Host) + endpoint.Host = canonicalAddr(endpoint) +} + +func (m *simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { + normalizeURL(&endpoint) m.RLock() defer m.RUnlock() @@ -70,9 +75,11 @@ func (m *simpleChallengeManager) AddResponse(resp *http.Response) error { } urlCopy := url.URL{ Path: resp.Request.URL.Path, - Host: strings.ToLower(resp.Request.URL.Host), + Host: resp.Request.URL.Host, Scheme: resp.Request.URL.Scheme, } + normalizeURL(&urlCopy) + m.Lock() defer m.Unlock() m.Challanges[urlCopy.String()] = challenges diff --git a/registry/client/auth/authchallenge_test.go b/registry/client/auth/authchallenge_test.go index e767ed74..2716fba5 100644 --- a/registry/client/auth/authchallenge_test.go +++ b/registry/client/auth/authchallenge_test.go @@ -44,6 +44,7 @@ func TestAuthChallengeParse(t *testing.T) { func TestAuthChallengeNormalization(t *testing.T) { testAuthChallengeNormalization(t, "reg.EXAMPLE.com") testAuthChallengeNormalization(t, "bɿɒʜɔiɿ-ɿɘƚƨim-ƚol-ɒ-ƨʞnɒʜƚ.com") + testAuthChallengeNormalization(t, "reg.example.com:80") testAuthChallengeConcurrent(t, "reg.EXAMPLE.com") } @@ -72,6 +73,7 @@ func testAuthChallengeNormalization(t *testing.T, host string) { lowered := *url lowered.Host = strings.ToLower(lowered.Host) + lowered.Host = canonicalAddr(&lowered) c, err := scm.GetChallenges(lowered) if err != nil { t.Fatal(err)