package client import ( "context" "crypto/tls" "fmt" "io" "net/http" "os" "path/filepath" "strconv" ) type Client struct { username string password string } func NewClient() *Client { return &Client{} } func NewClientWithAuth(username, password string) *Client { return &Client{ username: username, password: password, } } func (cli *Client) ServiceHello(ctx context.Context, ref string) (bool, error) { var res bool var err error ref, err = convertServiceRefer(ref) if err != nil { return res, err } req, err := http.NewRequestWithContext(ctx, http.MethodGet, ref, nil) if err != nil { return res, err } transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{ Transport: transport, } resp, err := client.Do(req) if err != nil { return res, err } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { res = true } return res, err } func (cli *Client) FileExists(ctx context.Context, ref string) (bool, error) { var res bool var err error ref, err = convertFileRefer(ref) if err != nil { return res, err } req, err := http.NewRequestWithContext(ctx, http.MethodHead, ref, nil) if err != nil { return res, err } if cli.username != "" && cli.password != "" { req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) } transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{ Transport: transport, } resp, err := client.Do(req) if err != nil { return res, err } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { res = true } return res, err } func (cli *Client) PutFile(ctx context.Context, filename, ref string) error { var err error ref, err = convertFileRefer(ref) if err != nil { return err } file, err := os.Open(filename) if err != nil { return err } defer file.Close() req, err := http.NewRequestWithContext(ctx, http.MethodPut, ref, file) if err != nil { return err } if cli.username != "" && cli.password != "" { req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) } transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{ Transport: transport, } fileinfo, err := os.Stat(filename) if err != nil { return err } filesize := fileinfo.Size() req.ContentLength = filesize req.Header.Set("Content-Type", "application/octet-stream") resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { err := fmt.Errorf("Received wrong status code: %s", resp.Status) return err } return err } func (cli *Client) GetFile(ctx context.Context, ref, filename string) (int64, error) { var err error var size int64 ref, err = convertFileRefer(ref) if err != nil { return size, err } req, err := http.NewRequestWithContext(ctx, http.MethodGet, ref, nil) if err != nil { return size, err } if cli.username != "" && cli.password != "" { req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) } transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{ Transport: transport, } resp, err := client.Do(req) if err != nil { return size, err } defer resp.Body.Close() contentLength := resp.Header.Get("Content-Length") if contentLength == "" { err = fmt.Errorf("Empty Content-Length received") return size, err } if resp.StatusCode != http.StatusOK { err := fmt.Errorf("Received wrong status code: %s", resp.Status) return size, err } declSize, err := strconv.ParseInt(contentLength, 10, 64) if err != nil { err = fmt.Errorf("Wrong Content-Length value: %v", err) return size, err } dirname := filepath.Dir(filename) err = os.MkdirAll(dirname, 0750) if err != nil { return size, err } file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0640) if err != nil { return size, err } size, err = io.Copy(file, resp.Body) if err != nil { return size, err } if size != declSize { err := fmt.Errorf("Mismatch Content-Length and recorded filesize") return size, err } return size, err } func (cli *Client) DeleteFile(ctx context.Context, ref, filename string) error { var err error ref, err = convertFileRefer(ref) if err != nil { return err } req, err := http.NewRequestWithContext(ctx, http.MethodDelete, ref, nil) if err != nil { return err } if cli.username != "" && cli.password != "" { req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) } transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{ Transport: transport, } resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { err := fmt.Errorf("Received wrong status code: %s", resp.Status) return err } return err }