github.com/auxten/ginkgo@v0.0.0-20220130172820-7d98ad59d232/download/http.go (about)

     1  package download
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net/http"
     7  	"net/url"
     8  	"sync"
     9  )
    10  
    11  type HttpDownloader struct {
    12  	sync.Once
    13  	client *http.Client
    14  }
    15  
    16  func (down *HttpDownloader) DownOffset(uri string, start int64, end int64) (r io.ReadCloser, err error) {
    17  	down.Do(func() {
    18  		down.client = &http.Client{}
    19  	})
    20  	var (
    21  		url    *url.URL
    22  		header http.Header
    23  		resp   *http.Response
    24  	)
    25  	if url, err = url.Parse(uri); err != nil {
    26  		return
    27  	}
    28  	if resp, err = down.client.Do(&http.Request{
    29  		Method: "GET",
    30  		URL:    url,
    31  		Header: SetByteRange(header, start, end),
    32  		Close:  false,
    33  	}); err != nil {
    34  		return
    35  	}
    36  
    37  	r = resp.Body
    38  	return
    39  }
    40  
    41  // SetContentRange sets 'Content-Range: bytes startPos-endPos/contentLength'
    42  // header.
    43  func SetContentRange(header http.Header, startPos, endPos, contentLength int64) http.Header {
    44  	if header == nil {
    45  		header = make(http.Header)
    46  	}
    47  	header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", startPos, endPos, contentLength))
    48  	return header
    49  }
    50  
    51  // SetByteRange sets 'Range: bytes=startPos-endPos' header.
    52  //
    53  //     * If startPos is negative, then 'bytes=-startPos' value is set.
    54  //     * If endPos is negative, then 'bytes=startPos-' value is set.
    55  func SetByteRange(header http.Header, startPos, endPos int64) http.Header {
    56  	if header == nil {
    57  		header = make(http.Header)
    58  	}
    59  	if startPos < 0 {
    60  		header.Set("Range", fmt.Sprintf("bytes=-%d", -startPos))
    61  	} else if endPos < 0 {
    62  		header.Set("Range", fmt.Sprintf("bytes=%d-", startPos))
    63  	} else {
    64  		header.Set("Range", fmt.Sprintf("bytes=%d-%d", startPos, endPos))
    65  	}
    66  	return header
    67  }