Repository: helm/helm
Pull request #13034 (2024-05-14 14:19:05)

ISSUE-9507: ADD `application/gzip,application/octet-stream` accept header
**What this PR does:**
This PR adds the accept header to the request sent by the HTTPGetter _when downloading archives_.

The function accepts gzip and so it would be preferable if it also notified the server about this. Additionally, this adds support for private helm charts hosted with GitHub.

**Special notes for your reviewer:**
Closes https://github.com/helm/helm/pull/11597
Closes https://github.com/helm/helm/issues/9507


Patch:
diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go
index a95894e00..dde6a1057 100644
--- a/pkg/downloader/chart_downloader.go
+++ b/pkg/downloader/chart_downloader.go
@@ -97,6 +97,8 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
 		return "", nil, err
 	}
 
+	c.Options = append(c.Options, getter.WithAcceptHeader("application/gzip,application/octet-stream"))
+
 	data, err := g.Get(u.String(), c.Options...)
 	if err != nil {
 		return "", nil, err
diff --git a/pkg/getter/getter.go b/pkg/getter/getter.go
index 45ab4da7e..1acb2093d 100644
--- a/pkg/getter/getter.go
+++ b/pkg/getter/getter.go
@@ -38,6 +38,7 @@ type options struct {
 	unTar                 bool
 	insecureSkipVerifyTLS bool
 	plainHTTP             bool
+	acceptHeader          string
 	username              string
 	password              string
 	passCredentialsAll    bool
@@ -60,6 +61,13 @@ func WithURL(url string) Option {
 	}
 }
 
+// WithAcceptHeader sets the request's Accept header as some REST APIs serve multiple content types
+func WithAcceptHeader(header string) Option {
+	return func(opts *options) {
+		opts.acceptHeader = header
+	}
+}
+
 // WithBasicAuth sets the request's Authorization header to use the provided credentials
 func WithBasicAuth(username, password string) Option {
 	return func(opts *options) {
diff --git a/pkg/getter/httpgetter.go b/pkg/getter/httpgetter.go
index b53e558e3..df3dcd910 100644
--- a/pkg/getter/httpgetter.go
+++ b/pkg/getter/httpgetter.go
@@ -53,6 +53,10 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) {
 		return nil, err
 	}
 
+	if g.opts.acceptHeader != "" {
+		req.Header.Set("Accept", g.opts.acceptHeader)
+	}
+
 	req.Header.Set("User-Agent", version.GetUserAgent())
 	if g.opts.userAgent != "" {
 		req.Header.Set("User-Agent", g.opts.userAgent)


Test patch:
diff --git a/pkg/getter/httpgetter_test.go b/pkg/getter/httpgetter_test.go
index 0ba7e03e8..2c38c6154 100644
--- a/pkg/getter/httpgetter_test.go
+++ b/pkg/getter/httpgetter_test.go
@@ -280,6 +280,29 @@ func TestDownload(t *testing.T) {
 	if got.String() != expect {
 		t.Errorf("Expected %q, got %q", expect, got.String())
 	}
+
+	// test server with varied Accept Header
+	const expectedAcceptHeader = "application/gzip,application/octet-stream"
+	acceptHeaderSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.Header.Get("Accept") != expectedAcceptHeader {
+			t.Errorf("Expected '%s', got '%s'", expectedAcceptHeader, r.Header.Get("Accept"))
+		}
+		fmt.Fprint(w, expect)
+	}))
+
+	defer acceptHeaderSrv.Close()
+
+	u, _ = url.ParseRequestURI(acceptHeaderSrv.URL)
+	httpgetter, err = NewHTTPGetter(
+		WithAcceptHeader(expectedAcceptHeader),
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = httpgetter.Get(u.String())
+	if err != nil {
+		t.Fatal(err)
+	}
 }
 
 func TestDownloadTLS(t *testing.T) {