Signed-off-by: Tibor Vass <tibor@docker.com>
| ... | ... |
@@ -12,11 +12,11 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
"github.com/Sirupsen/logrus" |
| 14 | 14 |
"github.com/docker/distribution/digest" |
| 15 |
+ "github.com/docker/distribution/registry/client/transport" |
|
| 15 | 16 |
"github.com/docker/docker/cliconfig" |
| 16 | 17 |
"github.com/docker/docker/pkg/progressreader" |
| 17 | 18 |
"github.com/docker/docker/pkg/streamformatter" |
| 18 | 19 |
"github.com/docker/docker/pkg/stringid" |
| 19 |
- "github.com/docker/docker/pkg/transport" |
|
| 20 | 20 |
"github.com/docker/docker/registry" |
| 21 | 21 |
"github.com/docker/docker/utils" |
| 22 | 22 |
) |
| ... | ... |
@@ -10,12 +10,12 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/Sirupsen/logrus" |
| 12 | 12 |
"github.com/docker/distribution/digest" |
| 13 |
+ "github.com/docker/distribution/registry/client/transport" |
|
| 13 | 14 |
"github.com/docker/docker/cliconfig" |
| 14 | 15 |
"github.com/docker/docker/pkg/ioutils" |
| 15 | 16 |
"github.com/docker/docker/pkg/progressreader" |
| 16 | 17 |
"github.com/docker/docker/pkg/streamformatter" |
| 17 | 18 |
"github.com/docker/docker/pkg/stringid" |
| 18 |
- "github.com/docker/docker/pkg/transport" |
|
| 19 | 19 |
"github.com/docker/docker/registry" |
| 20 | 20 |
"github.com/docker/docker/runconfig" |
| 21 | 21 |
"github.com/docker/docker/utils" |
| ... | ... |
@@ -225,3 +225,29 @@ func HashData(src io.Reader) (string, error) {
|
| 225 | 225 |
} |
| 226 | 226 |
return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil |
| 227 | 227 |
} |
| 228 |
+ |
|
| 229 |
+type OnEOFReader struct {
|
|
| 230 |
+ Rc io.ReadCloser |
|
| 231 |
+ Fn func() |
|
| 232 |
+} |
|
| 233 |
+ |
|
| 234 |
+func (r *OnEOFReader) Read(p []byte) (n int, err error) {
|
|
| 235 |
+ n, err = r.Rc.Read(p) |
|
| 236 |
+ if err == io.EOF {
|
|
| 237 |
+ r.runFunc() |
|
| 238 |
+ } |
|
| 239 |
+ return |
|
| 240 |
+} |
|
| 241 |
+ |
|
| 242 |
+func (r *OnEOFReader) Close() error {
|
|
| 243 |
+ err := r.Rc.Close() |
|
| 244 |
+ r.runFunc() |
|
| 245 |
+ return err |
|
| 246 |
+} |
|
| 247 |
+ |
|
| 248 |
+func (r *OnEOFReader) runFunc() {
|
|
| 249 |
+ if fn := r.Fn; fn != nil {
|
|
| 250 |
+ fn() |
|
| 251 |
+ r.Fn = nil |
|
| 252 |
+ } |
|
| 253 |
+} |
| 228 | 254 |
deleted file mode 100644 |
| ... | ... |
@@ -1,27 +0,0 @@ |
| 1 |
-Copyright (c) 2009 The oauth2 Authors. All rights reserved. |
|
| 2 |
- |
|
| 3 |
-Redistribution and use in source and binary forms, with or without |
|
| 4 |
-modification, are permitted provided that the following conditions are |
|
| 5 |
-met: |
|
| 6 |
- |
|
| 7 |
- * Redistributions of source code must retain the above copyright |
|
| 8 |
-notice, this list of conditions and the following disclaimer. |
|
| 9 |
- * Redistributions in binary form must reproduce the above |
|
| 10 |
-copyright notice, this list of conditions and the following disclaimer |
|
| 11 |
-in the documentation and/or other materials provided with the |
|
| 12 |
-distribution. |
|
| 13 |
- * Neither the name of Google Inc. nor the names of its |
|
| 14 |
-contributors may be used to endorse or promote products derived from |
|
| 15 |
-this software without specific prior written permission. |
|
| 16 |
- |
|
| 17 |
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 18 |
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 19 |
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 20 |
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 21 |
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 22 |
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 23 |
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 24 |
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 25 |
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 26 |
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 27 |
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,148 +0,0 @@ |
| 1 |
-package transport |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "io" |
|
| 5 |
- "net/http" |
|
| 6 |
- "sync" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-type RequestModifier interface {
|
|
| 10 |
- ModifyRequest(*http.Request) error |
|
| 11 |
-} |
|
| 12 |
- |
|
| 13 |
-type headerModifier http.Header |
|
| 14 |
- |
|
| 15 |
-// NewHeaderRequestModifier returns a RequestModifier that merges the HTTP headers |
|
| 16 |
-// passed as an argument, with the HTTP headers of a request. |
|
| 17 |
-// |
|
| 18 |
-// If the same key is present in both, the modifying header values for that key, |
|
| 19 |
-// are appended to the values for that same key in the request header. |
|
| 20 |
-func NewHeaderRequestModifier(header http.Header) RequestModifier {
|
|
| 21 |
- return headerModifier(header) |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func (h headerModifier) ModifyRequest(req *http.Request) error {
|
|
| 25 |
- for k, s := range http.Header(h) {
|
|
| 26 |
- req.Header[k] = append(req.Header[k], s...) |
|
| 27 |
- } |
|
| 28 |
- |
|
| 29 |
- return nil |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-// NewTransport returns an http.RoundTripper that modifies requests according to |
|
| 33 |
-// the RequestModifiers passed in the arguments, before sending the requests to |
|
| 34 |
-// the base http.RoundTripper (which, if nil, defaults to http.DefaultTransport). |
|
| 35 |
-func NewTransport(base http.RoundTripper, modifiers ...RequestModifier) http.RoundTripper {
|
|
| 36 |
- return &transport{
|
|
| 37 |
- Modifiers: modifiers, |
|
| 38 |
- Base: base, |
|
| 39 |
- } |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-// transport is an http.RoundTripper that makes HTTP requests after |
|
| 43 |
-// copying and modifying the request |
|
| 44 |
-type transport struct {
|
|
| 45 |
- Modifiers []RequestModifier |
|
| 46 |
- Base http.RoundTripper |
|
| 47 |
- |
|
| 48 |
- mu sync.Mutex // guards modReq |
|
| 49 |
- modReq map[*http.Request]*http.Request // original -> modified |
|
| 50 |
-} |
|
| 51 |
- |
|
| 52 |
-func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
| 53 |
- req2 := CloneRequest(req) |
|
| 54 |
- for _, modifier := range t.Modifiers {
|
|
| 55 |
- if err := modifier.ModifyRequest(req2); err != nil {
|
|
| 56 |
- return nil, err |
|
| 57 |
- } |
|
| 58 |
- } |
|
| 59 |
- |
|
| 60 |
- t.setModReq(req, req2) |
|
| 61 |
- res, err := t.base().RoundTrip(req2) |
|
| 62 |
- if err != nil {
|
|
| 63 |
- t.setModReq(req, nil) |
|
| 64 |
- return nil, err |
|
| 65 |
- } |
|
| 66 |
- res.Body = &OnEOFReader{
|
|
| 67 |
- Rc: res.Body, |
|
| 68 |
- Fn: func() { t.setModReq(req, nil) },
|
|
| 69 |
- } |
|
| 70 |
- return res, nil |
|
| 71 |
-} |
|
| 72 |
- |
|
| 73 |
-// CancelRequest cancels an in-flight request by closing its connection. |
|
| 74 |
-func (t *transport) CancelRequest(req *http.Request) {
|
|
| 75 |
- type canceler interface {
|
|
| 76 |
- CancelRequest(*http.Request) |
|
| 77 |
- } |
|
| 78 |
- if cr, ok := t.base().(canceler); ok {
|
|
| 79 |
- t.mu.Lock() |
|
| 80 |
- modReq := t.modReq[req] |
|
| 81 |
- delete(t.modReq, req) |
|
| 82 |
- t.mu.Unlock() |
|
| 83 |
- cr.CancelRequest(modReq) |
|
| 84 |
- } |
|
| 85 |
-} |
|
| 86 |
- |
|
| 87 |
-func (t *transport) base() http.RoundTripper {
|
|
| 88 |
- if t.Base != nil {
|
|
| 89 |
- return t.Base |
|
| 90 |
- } |
|
| 91 |
- return http.DefaultTransport |
|
| 92 |
-} |
|
| 93 |
- |
|
| 94 |
-func (t *transport) setModReq(orig, mod *http.Request) {
|
|
| 95 |
- t.mu.Lock() |
|
| 96 |
- defer t.mu.Unlock() |
|
| 97 |
- if t.modReq == nil {
|
|
| 98 |
- t.modReq = make(map[*http.Request]*http.Request) |
|
| 99 |
- } |
|
| 100 |
- if mod == nil {
|
|
| 101 |
- delete(t.modReq, orig) |
|
| 102 |
- } else {
|
|
| 103 |
- t.modReq[orig] = mod |
|
| 104 |
- } |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-// CloneRequest returns a clone of the provided *http.Request. |
|
| 108 |
-// The clone is a shallow copy of the struct and its Header map. |
|
| 109 |
-func CloneRequest(r *http.Request) *http.Request {
|
|
| 110 |
- // shallow copy of the struct |
|
| 111 |
- r2 := new(http.Request) |
|
| 112 |
- *r2 = *r |
|
| 113 |
- // deep copy of the Header |
|
| 114 |
- r2.Header = make(http.Header, len(r.Header)) |
|
| 115 |
- for k, s := range r.Header {
|
|
| 116 |
- r2.Header[k] = append([]string(nil), s...) |
|
| 117 |
- } |
|
| 118 |
- |
|
| 119 |
- return r2 |
|
| 120 |
-} |
|
| 121 |
- |
|
| 122 |
-// OnEOFReader ensures a callback function is called |
|
| 123 |
-// on Close() and when the underlying Reader returns an io.EOF error |
|
| 124 |
-type OnEOFReader struct {
|
|
| 125 |
- Rc io.ReadCloser |
|
| 126 |
- Fn func() |
|
| 127 |
-} |
|
| 128 |
- |
|
| 129 |
-func (r *OnEOFReader) Read(p []byte) (n int, err error) {
|
|
| 130 |
- n, err = r.Rc.Read(p) |
|
| 131 |
- if err == io.EOF {
|
|
| 132 |
- r.runFunc() |
|
| 133 |
- } |
|
| 134 |
- return |
|
| 135 |
-} |
|
| 136 |
- |
|
| 137 |
-func (r *OnEOFReader) Close() error {
|
|
| 138 |
- err := r.Rc.Close() |
|
| 139 |
- r.runFunc() |
|
| 140 |
- return err |
|
| 141 |
-} |
|
| 142 |
- |
|
| 143 |
-func (r *OnEOFReader) runFunc() {
|
|
| 144 |
- if fn := r.Fn; fn != nil {
|
|
| 145 |
- fn() |
|
| 146 |
- r.Fn = nil |
|
| 147 |
- } |
|
| 148 |
-} |
| ... | ... |
@@ -17,11 +17,11 @@ import ( |
| 17 | 17 |
"time" |
| 18 | 18 |
|
| 19 | 19 |
"github.com/Sirupsen/logrus" |
| 20 |
+ "github.com/docker/distribution/registry/client/transport" |
|
| 20 | 21 |
"github.com/docker/docker/autogen/dockerversion" |
| 21 | 22 |
"github.com/docker/docker/pkg/parsers/kernel" |
| 22 | 23 |
"github.com/docker/docker/pkg/timeoutconn" |
| 23 | 24 |
"github.com/docker/docker/pkg/tlsconfig" |
| 24 |
- "github.com/docker/docker/pkg/transport" |
|
| 25 | 25 |
"github.com/docker/docker/pkg/useragent" |
| 26 | 26 |
) |
| 27 | 27 |
|
| ... | ... |
@@ -92,7 +92,7 @@ func (m *httpsRequestModifier) ModifyRequest(req *http.Request) error {
|
| 92 | 92 |
logrus.Debugf("hostDir: %s", hostDir)
|
| 93 | 93 |
fs, err := ioutil.ReadDir(hostDir) |
| 94 | 94 |
if err != nil && !os.IsNotExist(err) {
|
| 95 |
- return nil |
|
| 95 |
+ return err |
|
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 | 98 |
for _, f := range fs {
|
| ... | ... |
@@ -22,8 +22,8 @@ import ( |
| 22 | 22 |
"github.com/Sirupsen/logrus" |
| 23 | 23 |
"github.com/docker/docker/cliconfig" |
| 24 | 24 |
"github.com/docker/docker/pkg/httputils" |
| 25 |
+ "github.com/docker/docker/pkg/ioutils" |
|
| 25 | 26 |
"github.com/docker/docker/pkg/tarsum" |
| 26 |
- "github.com/docker/docker/pkg/transport" |
|
| 27 | 27 |
) |
| 28 | 28 |
|
| 29 | 29 |
var ( |
| ... | ... |
@@ -73,6 +73,21 @@ func AuthTransport(base http.RoundTripper, authConfig *cliconfig.AuthConfig, alw |
| 73 | 73 |
} |
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 |
+// cloneRequest returns a clone of the provided *http.Request. |
|
| 77 |
+// The clone is a shallow copy of the struct and its Header map. |
|
| 78 |
+func cloneRequest(r *http.Request) *http.Request {
|
|
| 79 |
+ // shallow copy of the struct |
|
| 80 |
+ r2 := new(http.Request) |
|
| 81 |
+ *r2 = *r |
|
| 82 |
+ // deep copy of the Header |
|
| 83 |
+ r2.Header = make(http.Header, len(r.Header)) |
|
| 84 |
+ for k, s := range r.Header {
|
|
| 85 |
+ r2.Header[k] = append([]string(nil), s...) |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ return r2 |
|
| 89 |
+} |
|
| 90 |
+ |
|
| 76 | 91 |
func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) {
|
| 77 | 92 |
// Authorization should not be set on 302 redirect for untrusted locations. |
| 78 | 93 |
// This logic mirrors the behavior in AddRequiredHeadersToRedirectedRequests. |
| ... | ... |
@@ -112,7 +127,7 @@ func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) {
|
| 112 | 112 |
if len(resp.Header["X-Docker-Token"]) > 0 {
|
| 113 | 113 |
tr.token = resp.Header["X-Docker-Token"] |
| 114 | 114 |
} |
| 115 |
- resp.Body = &transport.OnEOFReader{
|
|
| 115 |
+ resp.Body = &ioutils.OnEOFReader{
|
|
| 116 | 116 |
Rc: resp.Body, |
| 117 | 117 |
Fn: func() {
|
| 118 | 118 |
tr.mu.Lock() |