github.com/cloudfoundry/cli@v7.1.0+incompatible/util/download/downloader.go (about)

     1  package download
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"net"
     7  	"net/http"
     8  	"os"
     9  	"path/filepath"
    10  	"time"
    11  
    12  	"code.cloudfoundry.org/cli/util"
    13  )
    14  
    15  type Downloader struct {
    16  	HTTPClient HTTPClient
    17  }
    18  
    19  func NewDownloader(dialTimeout time.Duration) *Downloader {
    20  	tr := &http.Transport{
    21  		TLSClientConfig: util.NewTLSConfig(nil, false),
    22  		Proxy:           http.ProxyFromEnvironment,
    23  		DialContext: (&net.Dialer{
    24  			KeepAlive: 30 * time.Second,
    25  			Timeout:   dialTimeout,
    26  		}).DialContext,
    27  	}
    28  
    29  	return &Downloader{
    30  		HTTPClient: &http.Client{
    31  			Transport: tr,
    32  		},
    33  	}
    34  }
    35  
    36  func (downloader Downloader) Download(url string, tmpDirPath string) (string, error) {
    37  	bpFileName := filepath.Join(tmpDirPath, filepath.Base(url))
    38  
    39  	resp, err := downloader.HTTPClient.Get(url)
    40  	if err != nil {
    41  		return bpFileName, err
    42  	}
    43  	defer resp.Body.Close()
    44  
    45  	if resp.StatusCode >= 400 {
    46  		rawBytes, readErr := ioutil.ReadAll(resp.Body)
    47  		if readErr != nil {
    48  			return bpFileName, readErr
    49  		}
    50  		return bpFileName, RawHTTPStatusError{
    51  			Status:      resp.Status,
    52  			RawResponse: rawBytes,
    53  		}
    54  	}
    55  
    56  	file, err := os.Create(bpFileName)
    57  	if err != nil {
    58  		return bpFileName, err
    59  	}
    60  	defer file.Close()
    61  
    62  	_, err = io.Copy(file, resp.Body)
    63  	if err != nil {
    64  		return bpFileName, err
    65  	}
    66  
    67  	return bpFileName, nil
    68  }