Example #1
0
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
}
Example #2
0
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
}