http2: make Transport handle HEAD responses with DATA frames

The Google GFE replies to HEAD requests with the END_STREAM bit in an
empty DATA frame, not in the response HEADERS. The Go Transport code
mistook this to mean the Content-Length was real.

Worked around in:
https://github.com/GoogleCloudPlatform/gcloud-golang/commit/645322e7db5d89c44d1f3925028479ac7dbc8680

Reported internally in b/27820181.

Change-Id: Id31a047e2277d7d90560fca264919e239ec76d74
Reviewed-on: https://go-review.googlesource.com/21061
Reviewed-by: Dave Day <djd@golang.org>
diff --git a/http2/transport_test.go b/http2/transport_test.go
index 556756a..07598b2 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -1738,3 +1738,60 @@
 		}
 	}
 }
+
+// The Google GFE responds to HEAD requests with a HEADERS frame
+// without END_STREAM, followed by a 0-length DATA frame with
+// END_STREAM. Make sure we don't get confused by that. (We did.)
+func TestTransportReadHeadResponse(t *testing.T) {
+	ct := newClientTester(t)
+	clientDone := make(chan struct{})
+	ct.client = func() error {
+		defer close(clientDone)
+		req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
+		res, err := ct.tr.RoundTrip(req)
+		if err != nil {
+			return err
+		}
+		if res.ContentLength != 123 {
+			return fmt.Errorf("Content-Length = %d; want 123", res.ContentLength)
+		}
+		slurp, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			return fmt.Errorf("ReadAll: %v", err)
+		}
+		if len(slurp) > 0 {
+			return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
+		}
+		return nil
+	}
+	ct.server = func() error {
+		ct.greet()
+		for {
+			f, err := ct.fr.ReadFrame()
+			if err != nil {
+				t.Logf("ReadFrame: %v", err)
+				return nil
+			}
+			hf, ok := f.(*HeadersFrame)
+			if !ok {
+				continue
+			}
+			var buf bytes.Buffer
+			enc := hpack.NewEncoder(&buf)
+			enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+			enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
+			ct.fr.WriteHeaders(HeadersFrameParam{
+				StreamID:      hf.StreamID,
+				EndHeaders:    true,
+				EndStream:     false, // as the GFE does
+				BlockFragment: buf.Bytes(),
+			})
+			ct.fr.WriteData(hf.StreamID, true, nil)
+
+			<-clientDone
+			return nil
+		}
+		return nil
+	}
+	ct.run()
+}