From 4c1b6a881e61f0ea6ccef187288ea26e3472e8d1 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Fri, 14 Jan 2022 10:08:53 -0500 Subject: [PATCH] Add --http-timeout flag Closes #43 --- CHANGELOG.md | 2 ++ binrepo.go | 10 ++++++---- cmd/gvm/gvm.go | 4 +++- common/common.go | 8 ++++---- gvm.go | 7 +++++++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 571bd10..c6e78ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Add `--http-timeout` flag to control the timeout for HTTP requests. [#43](https://github.com/andrewkroh/gvm/issues/43) [#45](https://github.com/andrewkroh/gvm/pull/45) + ## [0.3.2] ### Added diff --git a/binrepo.go b/binrepo.go index 55cec53..bbb9b1a 100644 --- a/binrepo.go +++ b/binrepo.go @@ -32,7 +32,7 @@ func (m *Manager) installBinary(version *GoVersion) (string, error) { } goURL := fmt.Sprintf("%s/go%v.%v-%v.%v", m.GoStorageHome, version, m.GOOS, m.GOARCH, extension) - path, err := common.DownloadFile(goURL, tmp) + path, err := common.DownloadFile(goURL, tmp, m.HTTPTimeout) if err != nil { return "", fmt.Errorf("failed downloading from %v: %w", goURL, err) } @@ -44,7 +44,7 @@ func (m *Manager) AvailableBinaries() ([]*GoVersion, error) { home, goos, goarch := m.GoStorageHome, m.GOOS, m.GOARCH versions := map[string]struct{}{} - err := iterXMLDirListing(home, func(name string) bool { + err := m.iterXMLDirListing(home, func(name string) bool { matches := reGostoreVersion.FindStringSubmatch(name) if len(matches) < 4 { return true @@ -76,9 +76,11 @@ func (m *Manager) AvailableBinaries() ([]*GoVersion, error) { return list, nil } -func iterXMLDirListing(home string, fn func(entry string) bool) error { +func (m *Manager) iterXMLDirListing(home string, fn func(entry string) bool) error { marker := "" - client := &http.Client{} + client := &http.Client{ + Timeout: m.HTTPTimeout, + } for { type contents struct { diff --git a/cmd/gvm/gvm.go b/cmd/gvm/gvm.go index 0578953..ed25416 100644 --- a/cmd/gvm/gvm.go +++ b/cmd/gvm/gvm.go @@ -33,7 +33,6 @@ var ( type commandFactory func(*kingpin.CmdClause) func(*gvm.Manager) error func main() { - app := kingpin.New("gvm", usage) debug := app.Flag("debug", "Enable debug logging to stderr.").Short('d').Bool() @@ -53,6 +52,7 @@ func main() { app.Flag("home", "GVM home directory.").StringVar(&manager.Home) app.Flag("url", "Go binaries repository base URL.").StringVar(&manager.GoStorageHome) app.Flag("repository", "Go upstream git repository.").StringVar(&manager.GoSourceURL) + app.Flag("http-timeout", "Timeout for HTTP requests.").Default("3m").DurationVar(&manager.HTTPTimeout) command(useCommand, "use", "prepare go version and print environment variables"). Default() @@ -85,6 +85,8 @@ func main() { os.Exit(1) } + logrus.Debug("GVM version: ", version) + action, exists := commands[selCommand] if !exists { app.Errorf("unknown command: %v", selCommand) diff --git a/common/common.go b/common/common.go index d9b868b..881e0cc 100644 --- a/common/common.go +++ b/common/common.go @@ -18,13 +18,13 @@ var log = logrus.WithField("package", "common") // ErrNotFound is returned when the download fails due to HTTP 404 Not Found. var ErrNotFound = errors.New("not found") -func DownloadFile(url, destinationDir string) (string, error) { +func DownloadFile(url, destinationDir string, httpTimeout time.Duration) (string, error) { log.WithField("url", url).Debug("Downloading file") var name string var err error var retry bool for a := 1; a <= 3; a++ { - name, err, retry = downloadFile(url, destinationDir) + name, err, retry = downloadFile(url, destinationDir, httpTimeout) if err != nil && retry { log.WithError(err).Debugf("Download attempt %d failed", a) continue @@ -34,9 +34,9 @@ func DownloadFile(url, destinationDir string) (string, error) { return name, err } -func downloadFile(url, destinationDir string) (path string, err error, retryable bool) { +func downloadFile(url, destinationDir string, httpTimeout time.Duration) (path string, err error, retryable bool) { client := http.Client{ - Timeout: time.Duration(3 * time.Minute), + Timeout: httpTimeout, } resp, err := client.Get(url) if err != nil { diff --git a/gvm.go b/gvm.go index ec7b084..e3379e4 100644 --- a/gvm.go +++ b/gvm.go @@ -9,6 +9,7 @@ import ( "runtime" "sort" "strings" + "time" "github.com/sirupsen/logrus" @@ -53,6 +54,8 @@ type Manager struct { // Defaults to https://go.googlesource.com/go GoSourceURL string + HTTPTimeout time.Duration + Logger logrus.FieldLogger cacheDir string @@ -78,6 +81,10 @@ func (m *Manager) Init() error { m.GoSourceURL = "https://go.googlesource.com/go" } + if m.HTTPTimeout == 0 { + m.HTTPTimeout = 3 * time.Minute + } + if m.GOOS == "" { m.GOOS = runtime.GOOS }