Skip to content

Commit b80e5db

Browse files
committed
util/resolver: Http fallback in the same host
If both Insecure and PlainHTTP is requested for the host, use a transport that falls back to HTTP in case of an HTTP request to a HTTPS client error. This also changes the order - before that an HTTP connection was attempted first. Now an HTTPS connection with insecure TLS check will be attempted first and will only fallback to HTTP if the former fails. This fixes push to an insecure HTTPS-only registry. Signed-off-by: Paweł Gronowski <[email protected]> (cherry picked from commit 1096d71) Signed-off-by: Paweł Gronowski <[email protected]>
1 parent f94ed7c commit b80e5db

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

util/resolver/resolver.go

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,25 @@ func fillInsecureOpts(host string, c config.RegistryConfig, h docker.RegistryHos
4040
}
4141
}
4242

43-
if isHTTP {
44-
h2 := h
45-
h2.Scheme = "http"
46-
hosts = append(hosts, h2)
47-
}
43+
httpsTransport := newDefaultTransport()
44+
httpsTransport.TLSClientConfig = tc
45+
4846
if c.Insecure != nil && *c.Insecure {
4947
h2 := h
50-
transport := newDefaultTransport()
51-
transport.TLSClientConfig = tc
48+
49+
var transport http.RoundTripper = httpsTransport
50+
if isHTTP {
51+
transport = &httpFallback{super: transport}
52+
}
5253
h2.Client = &http.Client{
5354
Transport: tracing.NewTransport(transport),
5455
}
5556
tc.InsecureSkipVerify = true
5657
hosts = append(hosts, h2)
58+
} else if isHTTP {
59+
h2 := h
60+
h2.Scheme = "http"
61+
hosts = append(hosts, h2)
5762
}
5863

5964
if len(hosts) == 0 {
@@ -210,3 +215,29 @@ func newDefaultTransport() *http.Transport {
210215
TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
211216
}
212217
}
218+
219+
type httpFallback struct {
220+
super http.RoundTripper
221+
fallback bool
222+
}
223+
224+
func (f *httpFallback) RoundTrip(r *http.Request) (*http.Response, error) {
225+
if !f.fallback {
226+
resp, err := f.super.RoundTrip(r)
227+
var tlsErr tls.RecordHeaderError
228+
if errors.As(err, &tlsErr) && string(tlsErr.RecordHeader[:]) == "HTTP/" {
229+
// Server gave HTTP response to HTTPS client
230+
f.fallback = true
231+
} else {
232+
return resp, err
233+
}
234+
}
235+
236+
plainHTTPUrl := *r.URL
237+
plainHTTPUrl.Scheme = "http"
238+
239+
plainHTTPRequest := *r
240+
plainHTTPRequest.URL = &plainHTTPUrl
241+
242+
return f.super.RoundTrip(&plainHTTPRequest)
243+
}

0 commit comments

Comments
 (0)