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 }