62 lines · 1.7 KB · Go
RawDownload
package httpfetch import (	"context"	"fmt"	"io"	"net/http"	"strings" 	log "github.com/sirupsen/logrus") // Doer abstracts the HTTP client used to execute requests.type Doer interface {	Do(*http.Request) (*http.Response, error)} // GetBytes performs a GET request with the supplied headers, requires a// success status, and returns the response body. When maxSize is positive// the body is rejected once it exceeds maxSize bytes.func GetBytes(ctx context.Context, client Doer, requestURL string, headers map[string]string, maxSize int64) ([]byte, error) {	if client == nil {		client = http.DefaultClient	}	req, errRequest := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)	if errRequest != nil {		return nil, fmt.Errorf("create request: %w", errRequest)	}	for key, value := range headers {		if value != "" {			req.Header.Set(key, value)		}	} 	resp, errDo := client.Do(req)	if errDo != nil {		return nil, fmt.Errorf("request failed: %w", errDo)	}	defer func() {		if errClose := resp.Body.Close(); errClose != nil {			log.WithError(errClose).Debug("failed to close response body")		}	}() 	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {		body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))		return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))	} 	reader := io.Reader(resp.Body)	if maxSize > 0 {		reader = io.LimitReader(resp.Body, maxSize+1)	}	data, errRead := io.ReadAll(reader)	if errRead != nil {		return nil, fmt.Errorf("read response: %w", errRead)	}	if maxSize > 0 && int64(len(data)) > maxSize {		return nil, fmt.Errorf("response exceeds maximum allowed size of %d bytes", maxSize)	}	return data, nil}