github.com/doitroot/helm@v3.0.0-beta.3+incompatible/pkg/getter/httpgetter.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package getter
    17  
    18  import (
    19  	"bytes"
    20  	"io"
    21  	"net/http"
    22  
    23  	"github.com/pkg/errors"
    24  
    25  	"helm.sh/helm/internal/tlsutil"
    26  	"helm.sh/helm/internal/urlutil"
    27  	"helm.sh/helm/internal/version"
    28  )
    29  
    30  // HTTPGetter is the efault HTTP(/S) backend handler
    31  type HTTPGetter struct {
    32  	client *http.Client
    33  	opts   options
    34  }
    35  
    36  //Get performs a Get from repo.Getter and returns the body.
    37  func (g *HTTPGetter) Get(href string, options ...Option) (*bytes.Buffer, error) {
    38  	for _, opt := range options {
    39  		opt(&g.opts)
    40  	}
    41  	return g.get(href)
    42  }
    43  
    44  func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) {
    45  	buf := bytes.NewBuffer(nil)
    46  
    47  	// Set a helm specific user agent so that a repo server and metrics can
    48  	// separate helm calls from other tools interacting with repos.
    49  	req, err := http.NewRequest("GET", href, nil)
    50  	if err != nil {
    51  		return buf, err
    52  	}
    53  
    54  	req.Header.Set("User-Agent", version.GetUserAgent())
    55  	if g.opts.userAgent != "" {
    56  		req.Header.Set("User-Agent", g.opts.userAgent)
    57  	}
    58  
    59  	if g.opts.username != "" && g.opts.password != "" {
    60  		req.SetBasicAuth(g.opts.username, g.opts.password)
    61  	}
    62  
    63  	resp, err := g.client.Do(req)
    64  	if err != nil {
    65  		return buf, err
    66  	}
    67  	if resp.StatusCode != 200 {
    68  		return buf, errors.Errorf("failed to fetch %s : %s", href, resp.Status)
    69  	}
    70  
    71  	_, err = io.Copy(buf, resp.Body)
    72  	resp.Body.Close()
    73  	return buf, err
    74  }
    75  
    76  // NewHTTPGetter constructs a valid http/https client as a Getter
    77  func NewHTTPGetter(options ...Option) (Getter, error) {
    78  	var client HTTPGetter
    79  
    80  	for _, opt := range options {
    81  		opt(&client.opts)
    82  	}
    83  
    84  	if client.opts.certFile != "" && client.opts.keyFile != "" {
    85  		tlsConf, err := tlsutil.NewClientTLS(client.opts.certFile, client.opts.keyFile, client.opts.caFile)
    86  		if err != nil {
    87  			return &client, errors.Wrap(err, "can't create TLS config for client")
    88  		}
    89  		tlsConf.BuildNameToCertificate()
    90  
    91  		sni, err := urlutil.ExtractHostname(client.opts.url)
    92  		if err != nil {
    93  			return &client, err
    94  		}
    95  		tlsConf.ServerName = sni
    96  
    97  		client.client = &http.Client{
    98  			Transport: &http.Transport{
    99  				TLSClientConfig: tlsConf,
   100  				Proxy:           http.ProxyFromEnvironment,
   101  			},
   102  		}
   103  	} else {
   104  		client.client = http.DefaultClient
   105  	}
   106  
   107  	return &client, nil
   108  }