diff --git a/components/engine/graph/pull.go b/components/engine/graph/pull.go index ae0e1f8e69..5f779f76fe 100644 --- a/components/engine/graph/pull.go +++ b/components/engine/graph/pull.go @@ -12,11 +12,11 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/digest" + "github.com/docker/distribution/registry/client/transport" "github.com/docker/docker/cliconfig" "github.com/docker/docker/pkg/progressreader" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/transport" "github.com/docker/docker/registry" "github.com/docker/docker/utils" ) diff --git a/components/engine/graph/push.go b/components/engine/graph/push.go index 628bb3157a..2f6908a465 100644 --- a/components/engine/graph/push.go +++ b/components/engine/graph/push.go @@ -10,12 +10,12 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/digest" + "github.com/docker/distribution/registry/client/transport" "github.com/docker/docker/cliconfig" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/progressreader" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/transport" "github.com/docker/docker/registry" "github.com/docker/docker/runconfig" "github.com/docker/docker/utils" diff --git a/components/engine/pkg/ioutils/readers.go b/components/engine/pkg/ioutils/readers.go index 0e542cbad3..f852a9399d 100644 --- a/components/engine/pkg/ioutils/readers.go +++ b/components/engine/pkg/ioutils/readers.go @@ -225,3 +225,29 @@ func HashData(src io.Reader) (string, error) { } return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil } + +type OnEOFReader struct { + Rc io.ReadCloser + Fn func() +} + +func (r *OnEOFReader) Read(p []byte) (n int, err error) { + n, err = r.Rc.Read(p) + if err == io.EOF { + r.runFunc() + } + return +} + +func (r *OnEOFReader) Close() error { + err := r.Rc.Close() + r.runFunc() + return err +} + +func (r *OnEOFReader) runFunc() { + if fn := r.Fn; fn != nil { + fn() + r.Fn = nil + } +} diff --git a/components/engine/pkg/transport/LICENSE b/components/engine/pkg/transport/LICENSE deleted file mode 100644 index d02f24fd52..0000000000 --- a/components/engine/pkg/transport/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The oauth2 Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/components/engine/pkg/transport/transport.go b/components/engine/pkg/transport/transport.go deleted file mode 100644 index 510d8b4bc2..0000000000 --- a/components/engine/pkg/transport/transport.go +++ /dev/null @@ -1,148 +0,0 @@ -package transport - -import ( - "io" - "net/http" - "sync" -) - -type RequestModifier interface { - ModifyRequest(*http.Request) error -} - -type headerModifier http.Header - -// NewHeaderRequestModifier returns a RequestModifier that merges the HTTP headers -// passed as an argument, with the HTTP headers of a request. -// -// If the same key is present in both, the modifying header values for that key, -// are appended to the values for that same key in the request header. -func NewHeaderRequestModifier(header http.Header) RequestModifier { - return headerModifier(header) -} - -func (h headerModifier) ModifyRequest(req *http.Request) error { - for k, s := range http.Header(h) { - req.Header[k] = append(req.Header[k], s...) - } - - return nil -} - -// NewTransport returns an http.RoundTripper that modifies requests according to -// the RequestModifiers passed in the arguments, before sending the requests to -// the base http.RoundTripper (which, if nil, defaults to http.DefaultTransport). -func NewTransport(base http.RoundTripper, modifiers ...RequestModifier) http.RoundTripper { - return &transport{ - Modifiers: modifiers, - Base: base, - } -} - -// transport is an http.RoundTripper that makes HTTP requests after -// copying and modifying the request -type transport struct { - Modifiers []RequestModifier - Base http.RoundTripper - - mu sync.Mutex // guards modReq - modReq map[*http.Request]*http.Request // original -> modified -} - -func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { - req2 := CloneRequest(req) - for _, modifier := range t.Modifiers { - if err := modifier.ModifyRequest(req2); err != nil { - return nil, err - } - } - - t.setModReq(req, req2) - res, err := t.base().RoundTrip(req2) - if err != nil { - t.setModReq(req, nil) - return nil, err - } - res.Body = &OnEOFReader{ - Rc: res.Body, - Fn: func() { t.setModReq(req, nil) }, - } - return res, nil -} - -// CancelRequest cancels an in-flight request by closing its connection. -func (t *transport) CancelRequest(req *http.Request) { - type canceler interface { - CancelRequest(*http.Request) - } - if cr, ok := t.base().(canceler); ok { - t.mu.Lock() - modReq := t.modReq[req] - delete(t.modReq, req) - t.mu.Unlock() - cr.CancelRequest(modReq) - } -} - -func (t *transport) base() http.RoundTripper { - if t.Base != nil { - return t.Base - } - return http.DefaultTransport -} - -func (t *transport) setModReq(orig, mod *http.Request) { - t.mu.Lock() - defer t.mu.Unlock() - if t.modReq == nil { - t.modReq = make(map[*http.Request]*http.Request) - } - if mod == nil { - delete(t.modReq, orig) - } else { - t.modReq[orig] = mod - } -} - -// CloneRequest returns a clone of the provided *http.Request. -// The clone is a shallow copy of the struct and its Header map. -func CloneRequest(r *http.Request) *http.Request { - // shallow copy of the struct - r2 := new(http.Request) - *r2 = *r - // deep copy of the Header - r2.Header = make(http.Header, len(r.Header)) - for k, s := range r.Header { - r2.Header[k] = append([]string(nil), s...) - } - - return r2 -} - -// OnEOFReader ensures a callback function is called -// on Close() and when the underlying Reader returns an io.EOF error -type OnEOFReader struct { - Rc io.ReadCloser - Fn func() -} - -func (r *OnEOFReader) Read(p []byte) (n int, err error) { - n, err = r.Rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -func (r *OnEOFReader) Close() error { - err := r.Rc.Close() - r.runFunc() - return err -} - -func (r *OnEOFReader) runFunc() { - if fn := r.Fn; fn != nil { - fn() - r.Fn = nil - } -} diff --git a/components/engine/registry/endpoint.go b/components/engine/registry/endpoint.go index ce92668f41..c21a426543 100644 --- a/components/engine/registry/endpoint.go +++ b/components/engine/registry/endpoint.go @@ -11,7 +11,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/api/v2" - "github.com/docker/docker/pkg/transport" + "github.com/docker/distribution/registry/client/transport" ) // for mocking in unit tests diff --git a/components/engine/registry/registry.go b/components/engine/registry/registry.go index fb08e5bdf0..f968daa841 100644 --- a/components/engine/registry/registry.go +++ b/components/engine/registry/registry.go @@ -17,11 +17,11 @@ import ( "time" "github.com/Sirupsen/logrus" + "github.com/docker/distribution/registry/client/transport" "github.com/docker/docker/autogen/dockerversion" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/timeoutconn" "github.com/docker/docker/pkg/tlsconfig" - "github.com/docker/docker/pkg/transport" "github.com/docker/docker/pkg/useragent" ) @@ -92,7 +92,7 @@ func (m *httpsRequestModifier) ModifyRequest(req *http.Request) error { logrus.Debugf("hostDir: %s", hostDir) fs, err := ioutil.ReadDir(hostDir) if err != nil && !os.IsNotExist(err) { - return nil + return err } for _, f := range fs { diff --git a/components/engine/registry/registry_test.go b/components/engine/registry/registry_test.go index 52a2dc30fb..d5e1a09587 100644 --- a/components/engine/registry/registry_test.go +++ b/components/engine/registry/registry_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" + "github.com/docker/distribution/registry/client/transport" "github.com/docker/docker/cliconfig" - "github.com/docker/docker/pkg/transport" ) var ( diff --git a/components/engine/registry/session.go b/components/engine/registry/session.go index 07195eb11b..3f3fd86fbf 100644 --- a/components/engine/registry/session.go +++ b/components/engine/registry/session.go @@ -22,8 +22,8 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/cliconfig" "github.com/docker/docker/pkg/httputils" + "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/tarsum" - "github.com/docker/docker/pkg/transport" ) var ( @@ -73,6 +73,21 @@ func AuthTransport(base http.RoundTripper, authConfig *cliconfig.AuthConfig, alw } } +// cloneRequest returns a clone of the provided *http.Request. +// The clone is a shallow copy of the struct and its Header map. +func cloneRequest(r *http.Request) *http.Request { + // shallow copy of the struct + r2 := new(http.Request) + *r2 = *r + // deep copy of the Header + r2.Header = make(http.Header, len(r.Header)) + for k, s := range r.Header { + r2.Header[k] = append([]string(nil), s...) + } + + return r2 +} + func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { // Authorization should not be set on 302 redirect for untrusted locations. // This logic mirrors the behavior in AddRequiredHeadersToRedirectedRequests. @@ -112,7 +127,7 @@ func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { if len(resp.Header["X-Docker-Token"]) > 0 { tr.token = resp.Header["X-Docker-Token"] } - resp.Body = &transport.OnEOFReader{ + resp.Body = &ioutils.OnEOFReader{ Rc: resp.Body, Fn: func() { tr.mu.Lock()