I’ve created the following simple code and it works as expected, as Im fairly new to go I would like to get some feedback, For error handling or if their a way to Write this code more elegant.
The public code is SaveOnFile
Gets info on artifact and auth, and downloads the artifact via url and user and password using HTTP client,
saves as temp file and returns path to file or error
The code will run as-as . The code
https://go.dev/play/p/8i_xZ-EVTvP
import (
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
"github.com/pkg/errors"
)
var errCode = errors.New("bad response status code")
var errFileNotWritten = errors.New("file not written")
var errDigest = errors.New("digest are not identical")
const (
statusMsg = `code: %d, response body:\n%s`
notWritten = `unable to write file %s from Response body`
msgDigestFailure = `target: \"%s\", file: \"%s\")`
msgFileNotClosed = `unable to close file %s`
)
func respBody(url string, user string, pass string) (io.ReadCloser, error) {
client := &http.Client{
Timeout: time.Second * 10,
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
if user != "" && pass != "" {
req.SetBasicAuth(user, pass)
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, errors.Wrapf(errCode, statusMsg, resp.StatusCode, resp.Body)
}
return resp.Body, nil
}
func classify(url string, user string, pass string) (string, error) {
const suffix = ".sha512"
rb, err := respBody(url+suffix, user, pass)
if err != nil {
return "", err
}
defer rb.Close()
bodyBytes, err := ioutil.ReadAll(rb)
if err != nil {
return "", err
}
return string(bodyBytes), nil
}
func downFile(url string, user string, pass string) (*os.File, error) {
responseBody, err := respBody(url, user, pass)
if err != nil {
return nil, err
}
defer responseBody.Close()
file, err := ioutil.TempFile("", "*")
if err != nil {
return nil, err
}
written, err := io.Copy(file, responseBody)
if err != nil {
return nil, errors.Wrapf(err, notWritten, file.Name())
} else if written <= 0 {
return nil, errors.Wrapf(errFileNotWritten, notWritten, file.Name())
}
if err := file.Close(); err != nil {
return nil, errors.Wrapf(err, msgFileNotClosed, file.Name())
}
return file, nil
}
func SaveAsFile(url string, digest string, user string, pass string) (string, error) {
file, err := downFile(url, user, pass)
if err != nil {
return "", err
}
if digest != "" {
targetDigest, err := classify(url, user, pass)
if err != nil {
return "", err
}
if strings.Compare(targetDigest, digest) != 0 {
return "", errors.Wrapf(errDigest, msgDigestFailure, targetDigest, digest)
}
}
return file.Name(), nil
}