Initial implementation.

This commit is contained in:
2020-07-31 13:12:54 +02:00
commit b2267537c5
3 changed files with 133 additions and 0 deletions

12
Makefile Normal file
View File

@ -0,0 +1,12 @@
BUILD_HASH := $(shell git describe --always --tags --long)
LDFLAGS := "-X main.version=${BUILD_HASH} -s -w"
.PHONY: install
install:
go fmt ./...
go install -ldflags ${LDFLAGS} ./...
.PHONY: build
build:
go fmt ./...
go build -ldflags ${LDFLAGS} ./...

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module gopkg.intern.drachenfels.de/goget
go 1.14

118
goget.go Normal file
View File

@ -0,0 +1,118 @@
package main
import (
"crypto/tls"
"flag"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"path"
"time"
)
var version string
type client struct {
User string
Password string
Insecure bool // disable certificate check
ConnectTimeout time.Duration
ReadTimeout time.Duration
Retries int
RetryWait time.Duration
}
func main() {
c := client{}
var filename string
var showVersion bool
flag.StringVar(&c.User, "http-user", "", "HTTP auth username")
flag.StringVar(&c.Password, "http-password", "", "HTTP auth password")
flag.IntVar(&c.Retries, "retries", 1, "Number of retries in case of download errors.")
flag.DurationVar(&c.RetryWait, "retry-wait", 2*time.Second, "Time to wait before retrying download.")
flag.DurationVar(&c.ConnectTimeout, "connect-timeout", 5*time.Second, "TCP connections that take longer to establish will be aborted")
flag.DurationVar(&c.ReadTimeout, "read-timeout", 10*time.Second, "TCP connections that that are longer idle will be aborted")
flag.BoolVar(&c.Insecure, "insecure", false, "Disable TLS certificate verification.")
flag.BoolVar(&showVersion, "version", false, "Show version and exit.")
flag.StringVar(&filename, "filename", "", "Filename / path where to write downloaded file to. Defaults to filename of the URL.")
flag.Parse()
if showVersion {
println("version:", version)
os.Exit(1)
}
downloadURI := flag.Args()[0]
if filename == "" {
uri, err := url.Parse(downloadURI)
if err != nil {
panic(err)
}
filename = path.Base(uri.Path)
}
var err error
for i := 0; i < c.Retries; i++ {
err = c.DownloadFile(filename, downloadURI)
if err == nil {
break
}
println(err.Error())
if c.RetryWait > 0 {
time.Sleep(c.RetryWait)
}
}
if err != nil {
os.Exit(1)
}
}
func (c *client) DownloadFile(filename string, url string) (err error) {
println("Downloading %s to file %s\n", url, filename)
// Create the target file
out, err := os.Create(filename)
if err != nil {
return err
}
defer out.Close()
tr := &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: c.ReadTimeout,
DisableCompression: true,
DialContext: (&net.Dialer{
Timeout: c.ConnectTimeout, // connect timeout
}).DialContext,
// TLSHandshakeTimeout: 5 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: c.Insecure,
},
}
client := &http.Client{Transport: tr}
// Get the data
resp, err := client.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// Check server response
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}
// Writer the body to file
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}