From 774b135776870bf3990a554c643825b23b63d4b6 Mon Sep 17 00:00:00 2001 From: prizov Date: Tue, 7 Jun 2022 17:03:15 +0300 Subject: [PATCH] Accept `gzip` for fetching a repository index file. The change introduces a new `getter` option - `enableCompression`, and enables the feature for downloading a repository index file. When the option value is `true`: - `HttpGetter` adds "Accept-Encoding: gzip" header to a request. - `HttpGetter` performs decompression of a response body if the response contains "Content-Encoding: gzip" header. Signed-off-by: Alex Prizov --- pkg/getter/getter.go | 8 ++++++++ pkg/getter/httpgetter.go | 19 ++++++++++++++++++- pkg/getter/httpgetter_test.go | 26 ++++++++++++++++++++++++++ pkg/repo/chartrepo.go | 1 + 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/pkg/getter/getter.go b/pkg/getter/getter.go index 653b032fe..821a177ad 100644 --- a/pkg/getter/getter.go +++ b/pkg/getter/getter.go @@ -42,6 +42,7 @@ type options struct { passCredentialsAll bool userAgent string version string + enableCompression bool registryClient *registry.Client timeout time.Duration transport *http.Transport @@ -115,6 +116,13 @@ func WithRegistryClient(client *registry.Client) Option { } } +// WithCompression enables compression +func WithCompression() Option { + return func(opts *options) { + opts.enableCompression = true + } +} + func WithUntar() Option { return func(opts *options) { opts.unTar = true diff --git a/pkg/getter/httpgetter.go b/pkg/getter/httpgetter.go index 6fe1aa71f..064dc7305 100644 --- a/pkg/getter/httpgetter.go +++ b/pkg/getter/httpgetter.go @@ -17,6 +17,7 @@ package getter import ( "bytes" + "compress/gzip" "crypto/tls" "io" "net/http" @@ -78,6 +79,10 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) { } } + if g.opts.enableCompression { + req.Header.Add("Accept-Encoding", "gzip") + } + client, err := g.httpClient() if err != nil { return nil, err @@ -93,7 +98,19 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) { } buf := bytes.NewBuffer(nil) - _, err = io.Copy(buf, resp.Body) + + body := resp.Body + + if g.opts.enableCompression && resp.Header.Get("Content-Encoding") == "gzip" { + body, err = gzip.NewReader(resp.Body) + if err != nil { + return nil, err + } + defer body.Close() + } + + _, err = io.Copy(buf, body) + return buf, err } diff --git a/pkg/getter/httpgetter_test.go b/pkg/getter/httpgetter_test.go index 140b2c714..14aae0ff1 100644 --- a/pkg/getter/httpgetter_test.go +++ b/pkg/getter/httpgetter_test.go @@ -16,6 +16,8 @@ limitations under the License. package getter import ( + "bytes" + "compress/gzip" "fmt" "io" "net/http" @@ -363,6 +365,30 @@ func TestDownloadInsecureSkipTLSVerify(t *testing.T) { } +func TestHTTPGetterWithCompression(t *testing.T) { + expectedData := []byte("index.yaml") + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Encoding", "gzip") + gzipWriter := gzip.NewWriter(w) + gzipWriter.Write(expectedData) + gzipWriter.Close() + })) + + defer srv.Close() + + g, err := NewHTTPGetter(WithURL(srv.URL), WithCompression()) + if err != nil { + t.Fatal(err) + } + + data, _ := g.Get(srv.URL) + + if bytes.Compare(data.Bytes(), expectedData) != 0 { + t.Fatalf("Expected response with uncompressed data %s, but got %s", expectedData, data.Bytes()) + } +} + func TestHTTPGetterTarDownload(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { f, _ := os.Open("testdata/empty-0.0.1.tgz") diff --git a/pkg/repo/chartrepo.go b/pkg/repo/chartrepo.go index 956997cc9..99ef60f48 100644 --- a/pkg/repo/chartrepo.go +++ b/pkg/repo/chartrepo.go @@ -131,6 +131,7 @@ func (r *ChartRepository) DownloadIndexFile() (string, error) { getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile), getter.WithBasicAuth(r.Config.Username, r.Config.Password), getter.WithPassCredentialsAll(r.Config.PassCredentialsAll), + getter.WithCompression(), ) if err != nil { return "", err