func (sr SimpleRetriever) GetChunked(req *Request, cancel <-chan bool) (*Chunked, error) { chunkCh := make(chan Chunk, 20) var finalErr error chunked := &Chunked{ Err: &finalErr, Chunks: chunkCh, } resp, err := http.DefaultTransport.RoundTrip(proxy.UnmarshalRequest(req.HttpRequest)) if err != nil { return nil, err } if resp.Header.Get("ETag") != req.Etag { resp.Body.Close() return nil, fmt.Errorf("ETag doesn't match expected value") } chunked.Header = Header{ StatusCode: resp.StatusCode, Status: resp.Status, ContentLength: resp.ContentLength, Header: resp.Header, } go func() { defer resp.Body.Close() defer close(chunkCh) offset := 0 finalErr = split.SplitFun(resp.Body, func(buf []byte) error { digest := sha256.New() if n, err := digest.Write(buf); err != nil || n < len(buf) { if err == nil { err = io.ErrShortWrite } return err } chunk := Chunk{ Offset: offset, Length: len(buf), Digest: digest.Sum(nil), } select { case <-cancel: return ErrCancel default: } select { case chunkCh <- chunk: case <-cancel: return ErrCancel } offset += len(buf) return nil }) }() return chunked, nil }
func getContents(req *proxy.Request, r byteRange) ([]byte, error) { httpReq := proxy.UnmarshalRequest(req) httpReq.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", r.begin, r.end-1)) resp, err := http.DefaultTransport.RoundTrip(httpReq) if err != nil { return nil, err } defer resp.Body.Close() if resp.Header.Get("Content-Range") == "" { // TODO: Do something more intelligent (check earlier if supported and check Content-Range's value) return nil, fmt.Errorf("No Content-Range in response") } contents, err := ioutil.ReadAll(resp.Body) if len(contents) != int(r.end-r.begin) { return nil, fmt.Errorf("Wrong length of range response %d %d %d", len(contents), r.end, r.begin) } return contents, err }