|
@@ -1738,3 +1738,60 @@ func TestTransportNewTLSConfig(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+// 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()
|
|
|
|
|
+}
|