diff --git a/pkg/apiserver/proxy.go b/pkg/apiserver/proxy.go index e358ffe2aa4..1acad7c386b 100644 --- a/pkg/apiserver/proxy.go +++ b/pkg/apiserver/proxy.go @@ -18,7 +18,9 @@ package apiserver import ( "bytes" + "compress/gzip" "fmt" + "io" "io/ioutil" "net/http" "net/http/httputil" @@ -225,17 +227,40 @@ func (t *proxyTransport) scan(n *html.Node, f func(*html.Node)) { // fixLinks modifies links in an HTML file such that they will be redirected through the proxy if needed. func (t *proxyTransport) fixLinks(req *http.Request, resp *http.Response) (*http.Response, error) { - defer resp.Body.Close() + origBody := resp.Body + defer origBody.Close() - doc, err := html.Parse(resp.Body) + newContent := &bytes.Buffer{} + var reader io.Reader = origBody + var writer io.Writer = newContent + encoding := resp.Header.Get("Content-Encoding") + switch encoding { + case "gzip": + var err error + reader, err = gzip.NewReader(reader) + if err != nil { + return nil, fmt.Errorf("errorf making gzip reader: %v", err) + } + gzw := gzip.NewWriter(writer) + defer gzw.Close() + writer = gzw + // TODO: support flate, other encodings. + case "": + // This is fine + default: + // Some encoding we don't understand-- don't try to parse this + glog.Errorf("Proxy encountered encoding %v for text/html; can't understand this so not fixing links.", encoding) + return resp, nil + } + + doc, err := html.Parse(reader) if err != nil { glog.Errorf("Parse failed: %v", err) return resp, err } - newContent := &bytes.Buffer{} t.scan(doc, func(n *html.Node) { t.updateURLs(n, req.URL) }) - if err := html.Render(newContent, doc); err != nil { + if err := html.Render(writer, doc); err != nil { glog.Errorf("Failed to render: %v", err) } diff --git a/pkg/apiserver/proxy_test.go b/pkg/apiserver/proxy_test.go index 9ab96a32134..c771e34a43c 100644 --- a/pkg/apiserver/proxy_test.go +++ b/pkg/apiserver/proxy_test.go @@ -18,7 +18,9 @@ package apiserver import ( "bytes" + "compress/gzip" "fmt" + "io" "io/ioutil" "net/http" "net/http/httptest" @@ -132,17 +134,19 @@ func TestProxyTransport_fixLinks(t *testing.T) { func TestProxy(t *testing.T) { table := []struct { - method string - path string - reqBody string - respBody string - reqNamespace string + method string + path string + reqBody string + respBody string + respContentType string + reqNamespace string }{ - {"GET", "/some/dir", "", "answer", "default"}, - {"POST", "/some/other/dir", "question", "answer", "default"}, - {"PUT", "/some/dir/id", "different question", "answer", "default"}, - {"DELETE", "/some/dir/id", "", "ok", "default"}, - {"GET", "/some/dir/id", "", "answer", "other"}, + {"GET", "/some/dir", "", "answer", "text/css", "default"}, + {"GET", "/some/dir", "", "answer", "text/html", "default"}, + {"POST", "/some/other/dir", "question", "answer", "text/css", "default"}, + {"PUT", "/some/dir/id", "different question", "answer", "text/css", "default"}, + {"DELETE", "/some/dir/id", "", "ok", "text/css", "default"}, + {"GET", "/some/dir/id", "", "answer", "text/css", "other"}, } for _, item := range table { @@ -157,7 +161,17 @@ func TestProxy(t *testing.T) { if e, a := item.path, req.URL.Path; e != a { t.Errorf("%v - expected %v, got %v", item.method, e, a) } - fmt.Fprint(w, item.respBody) + w.Header().Set("Content-Type", item.respContentType) + var out io.Writer = w + if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { + // The proxier can ask for gzip'd data; we need to provide it with that + // in order to test our processing of that data. + w.Header().Set("Content-Encoding", "gzip") + gzw := gzip.NewWriter(w) + out = gzw + defer gzw.Close() + } + fmt.Fprint(out, item.respBody) })) defer proxyServer.Close()