From 8f3c7497acd69d980d40f55ebf97ae2f9a7fd034 Mon Sep 17 00:00:00 2001 From: Dave Grijalva Date: Wed, 10 Aug 2011 14:16:13 -0700 Subject: [PATCH] http: corrects undocumented side effects in http.DefaultTransport's RoundTrip method Fixes #2140. The http.DefaultTransport's RoundTrip method leaves the http.Request object in an altered state after performing the round trip. This patch removes the header from the Request before returning to the client. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/4857041 --- src/pkg/http/transport.go | 3 ++ src/pkg/http/transport_test.go | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go index 3c16c880d5a..d03aadfd344 100644 --- a/src/pkg/http/transport.go +++ b/src/pkg/http/transport.go @@ -511,6 +511,9 @@ func (pc *persistConn) readLoop() { if err != nil || resp.ContentLength == 0 { return resp, err } + if rc.addedGzip { + forReq.Header.Del("Accept-Encoding") + } if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" { resp.Header.Del("Content-Encoding") resp.Header.Del("Content-Length") diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go index 76e97640e35..20895da8695 100644 --- a/src/pkg/http/transport_test.go +++ b/src/pkg/http/transport_test.go @@ -387,6 +387,68 @@ func TestTransportNilURL(t *testing.T) { } } +var roundTripTests = []struct { + accept string + expectAccept string + compressed bool +}{ + // Requests with no accept-encoding header use transparent compression + {"", "gzip", false}, + // Requests with other accept-encoding should pass through unmodified + {"foo", "foo", false}, + // Requests with accept-encoding == gzip should be passed through + {"gzip", "gzip", true}} + +// Test that the modification made to the Request by the RoundTripper is cleaned up +func TestRoundTripGzip(t *testing.T) { + const responseBody = "test response body" + ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { + accept := req.Header.Get("Accept-Encoding") + if expect := req.FormValue("expect_accept"); accept != expect { + t.Errorf("Accept-Encoding = %q, want %q", accept, expect) + } + if accept == "gzip" { + rw.Header().Set("Content-Encoding", "gzip") + gz, _ := gzip.NewWriter(rw) + gz.Write([]byte(responseBody)) + gz.Close() + } else { + rw.Header().Set("Content-Encoding", accept) + rw.Write([]byte(responseBody)) + } + })) + defer ts.Close() + + for i, test := range roundTripTests { + // Test basic request (no accept-encoding) + req, _ := NewRequest("GET", ts.URL+"?expect_accept="+test.expectAccept, nil) + req.Header.Set("Accept-Encoding", test.accept) + res, err := DefaultTransport.RoundTrip(req) + var body []byte + if test.compressed { + gzip, _ := gzip.NewReader(res.Body) + body, err = ioutil.ReadAll(gzip) + res.Body.Close() + } else { + body, err = ioutil.ReadAll(res.Body) + } + if err != nil { + t.Errorf("%d. Error: %q", i, err) + } else { + if g, e := string(body), responseBody; g != e { + t.Errorf("%d. body = %q; want %q", i, g, e) + } + if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e { + t.Errorf("%d. Accept-Encoding = %q; want %q", i, g, e) + } + if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e { + t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e) + } + } + } + +} + func TestTransportGzip(t *testing.T) { const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" const nRandBytes = 1024 * 1024