@@ -22,9 +22,7 @@ const (
2222 defaultPath = "/v2"
2323)
2424
25- func fillInsecureOpts (host string , c config.RegistryConfig , h docker.RegistryHost ) ([]docker.RegistryHost , error ) {
26- var hosts []docker.RegistryHost
27-
25+ func fillInsecureOpts (host string , c config.RegistryConfig , h docker.RegistryHost ) (* docker.RegistryHost , error ) {
2826 tc , err := loadTLSConfig (c )
2927 if err != nil {
3028 return nil , err
@@ -40,33 +38,31 @@ func fillInsecureOpts(host string, c config.RegistryConfig, h docker.RegistryHos
4038 }
4139 }
4240
43- if isHTTP {
44- h2 := h
45- h2 .Scheme = "http"
46- hosts = append (hosts , h2 )
47- }
41+ httpsTransport := newDefaultTransport ()
42+ httpsTransport .TLSClientConfig = tc
43+
4844 if c .Insecure != nil && * c .Insecure {
4945 h2 := h
50- transport := newDefaultTransport ()
51- transport .TLSClientConfig = tc
46+
47+ var transport http.RoundTripper = httpsTransport
48+ if isHTTP {
49+ transport = & httpFallback {super : transport }
50+ }
5251 h2 .Client = & http.Client {
5352 Transport : tracing .NewTransport (transport ),
5453 }
5554 tc .InsecureSkipVerify = true
56- hosts = append (hosts , h2 )
55+ return & h2 , nil
56+ } else if isHTTP {
57+ h2 := h
58+ h2 .Scheme = "http"
59+ return & h2 , nil
5760 }
5861
59- if len (hosts ) == 0 {
60- transport := newDefaultTransport ()
61- transport .TLSClientConfig = tc
62-
63- h .Client = & http.Client {
64- Transport : tracing .NewTransport (transport ),
65- }
66- hosts = append (hosts , h )
62+ h .Client = & http.Client {
63+ Transport : tracing .NewTransport (httpsTransport ),
6764 }
68-
69- return hosts , nil
65+ return & h , nil
7066}
7167
7268func loadTLSConfig (c config.RegistryConfig ) (* tls.Config , error ) {
@@ -133,12 +129,12 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts
133129 for _ , rawMirror := range c .Mirrors {
134130 h := newMirrorRegistryHost (rawMirror )
135131 mirrorHost := h .Host
136- hosts , err := fillInsecureOpts (mirrorHost , m [mirrorHost ], h )
132+ host , err := fillInsecureOpts (mirrorHost , m [mirrorHost ], h )
137133 if err != nil {
138134 return nil , err
139135 }
140136
141- out = append (out , hosts ... )
137+ out = append (out , * host )
142138 }
143139
144140 if host == "docker.io" {
@@ -158,7 +154,8 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts
158154 return nil , err
159155 }
160156
161- out = append (out , hosts ... )
157+ out = append (out , * hosts )
158+
162159 return out , nil
163160 },
164161 docker .ConfigureDefaultRegistries (
@@ -210,3 +207,29 @@ func newDefaultTransport() *http.Transport {
210207 TLSNextProto : make (map [string ]func (authority string , c * tls.Conn ) http.RoundTripper ),
211208 }
212209}
210+
211+ type httpFallback struct {
212+ super http.RoundTripper
213+ fallback bool
214+ }
215+
216+ func (f * httpFallback ) RoundTrip (r * http.Request ) (* http.Response , error ) {
217+ if ! f .fallback {
218+ resp , err := f .super .RoundTrip (r )
219+ var tlsErr tls.RecordHeaderError
220+ if errors .As (err , & tlsErr ) && string (tlsErr .RecordHeader [:]) == "HTTP/" {
221+ // Server gave HTTP response to HTTPS client
222+ f .fallback = true
223+ } else {
224+ return resp , err
225+ }
226+ }
227+
228+ plainHTTPUrl := * r .URL
229+ plainHTTPUrl .Scheme = "http"
230+
231+ plainHTTPRequest := * r
232+ plainHTTPRequest .URL = & plainHTTPUrl
233+
234+ return f .super .RoundTrip (& plainHTTPRequest )
235+ }
0 commit comments