From fb2142147fbde48cbcba16863e6080b452106ae0 Mon Sep 17 00:00:00 2001
From: Richard Scothern <richard.scothern@gmail.com>
Date: Mon, 7 Dec 2015 10:17:49 -0800
Subject: [PATCH] Add clearer messaging around missing content-length headers.
 Signed-off-by: Richard Scothern <richard.scothern@gmail.com>

---
 docs/client/repository.go      |  4 +++
 docs/client/repository_test.go | 53 ++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/docs/client/repository.go b/docs/client/repository.go
index fc709ded..f8bcaaaa 100644
--- a/docs/client/repository.go
+++ b/docs/client/repository.go
@@ -487,6 +487,10 @@ func (bs *blobStatter) Stat(ctx context.Context, dgst digest.Digest) (distributi
 
 	if SuccessStatus(resp.StatusCode) {
 		lengthHeader := resp.Header.Get("Content-Length")
+		if lengthHeader == "" {
+			return distribution.Descriptor{}, fmt.Errorf("missing content-length header for request: %s", u)
+		}
+
 		length, err := strconv.ParseInt(lengthHeader, 10, 64)
 		if err != nil {
 			return distribution.Descriptor{}, fmt.Errorf("error parsing content-length: %v", err)
diff --git a/docs/client/repository_test.go b/docs/client/repository_test.go
index 1e6eb25f..058947de 100644
--- a/docs/client/repository_test.go
+++ b/docs/client/repository_test.go
@@ -159,6 +159,59 @@ func TestBlobFetch(t *testing.T) {
 	// TODO(dmcgowan): Test for unknown blob case
 }
 
+func TestBlobExistsNoContentLength(t *testing.T) {
+	var m testutil.RequestResponseMap
+
+	repo := "biff"
+	dgst, content := newRandomBlob(1024)
+	m = append(m, testutil.RequestResponseMapping{
+		Request: testutil.Request{
+			Method: "GET",
+			Route:  "/v2/" + repo + "/blobs/" + dgst.String(),
+		},
+		Response: testutil.Response{
+			StatusCode: http.StatusOK,
+			Body:       content,
+			Headers: http.Header(map[string][]string{
+				//			"Content-Length": {fmt.Sprint(len(content))},
+				"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
+			}),
+		},
+	})
+
+	m = append(m, testutil.RequestResponseMapping{
+		Request: testutil.Request{
+			Method: "HEAD",
+			Route:  "/v2/" + repo + "/blobs/" + dgst.String(),
+		},
+		Response: testutil.Response{
+			StatusCode: http.StatusOK,
+			Headers: http.Header(map[string][]string{
+				//			"Content-Length": {fmt.Sprint(len(content))},
+				"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
+			}),
+		},
+	})
+	e, c := testServer(m)
+	defer c()
+
+	ctx := context.Background()
+	r, err := NewRepository(ctx, repo, e, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	l := r.Blobs(ctx)
+
+	_, err = l.Stat(ctx, dgst)
+	if err == nil {
+		t.Fatal(err)
+	}
+	if !strings.Contains(err.Error(), "missing content-length heade") {
+		t.Fatalf("Expected missing content-length error message")
+	}
+
+}
+
 func TestBlobExists(t *testing.T) {
 	d1, b1 := newRandomBlob(1024)
 	var m testutil.RequestResponseMap