github.com/adevinta/lava@v0.7.2/internal/urlutil/urlutil.go (about)

     1  // Copyright 2023 Adevinta
     2  
     3  // Package urlutil provides utilities for working with URLs.
     4  package urlutil
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"net/http"
    11  	"net/url"
    12  	"os"
    13  )
    14  
    15  var (
    16  	// ErrInvalidScheme is returned by [Get] when the scheme of
    17  	// the provided URL is not supported.
    18  	ErrInvalidScheme = errors.New("invalid scheme")
    19  
    20  	// ErrInvalidURL is returned by [Get] when the provided URL is
    21  	// not valid.
    22  	ErrInvalidURL = errors.New("invalid URL")
    23  )
    24  
    25  // Get retrieves the contents from a given raw URL. It returns error
    26  // if the URL is not valid or if it is not possible to get the
    27  // contents.
    28  //
    29  // It supports the following schemes: http, https. If the provided URL
    30  // does not specify a scheme, it is considered a file path. In the
    31  // case of http and https, the contents are retrieved issuing an HTTP
    32  // GET request.
    33  func Get(rawURL string) ([]byte, error) {
    34  	parsedURL, err := url.Parse(rawURL)
    35  	if err != nil {
    36  		return nil, fmt.Errorf("%w: %w", ErrInvalidURL, err)
    37  	}
    38  
    39  	switch parsedURL.Scheme {
    40  	case "http", "https":
    41  		return getHTTP(parsedURL)
    42  	case "":
    43  		return os.ReadFile(parsedURL.Path)
    44  	}
    45  	return nil, fmt.Errorf("%w: %v", ErrInvalidScheme, parsedURL.Scheme)
    46  }
    47  
    48  // getHTTP retrieves the contents of a given HTTP URL.
    49  func getHTTP(parsedURL *url.URL) ([]byte, error) {
    50  	resp, err := http.Get(parsedURL.String())
    51  	if err != nil {
    52  		return nil, fmt.Errorf("get %q: %w", parsedURL, err)
    53  	}
    54  	defer resp.Body.Close()
    55  
    56  	if resp.StatusCode != http.StatusOK {
    57  		return nil, fmt.Errorf("get %q: invalid status code: %v", parsedURL, resp.StatusCode)
    58  	}
    59  	return io.ReadAll(resp.Body)
    60  }