func (me *File) prepareReader() (err error) { if me.r != nil && me.off != me.rOff { me.r.Close() me.r = nil } if me.r != nil { return nil } if me.flags&missinggo.O_ACCMODE == os.O_WRONLY { err = errors.New("read flags missing") return } req, err := http.NewRequest("GET", me.url, nil) if err != nil { return } if me.off != 0 { req.Header.Set("Range", fmt.Sprintf("bytes=%d-", me.off)) } resp, err := me.fs.Client.Do(req) if err != nil { return } switch resp.StatusCode { case http.StatusPartialContent: cr, ok := missinggo.ParseHTTPBytesContentRange(resp.Header.Get("Content-Range")) if !ok || cr.First != me.off { err = errors.New("bad response") resp.Body.Close() return } me.length = cr.Length case http.StatusOK: if me.off != 0 { err = errors.New("bad response") resp.Body.Close() return } if h := resp.Header.Get("Content-Length"); h != "" { var cl uint64 cl, err = strconv.ParseUint(h, 10, 64) if err != nil { resp.Body.Close() return } me.length = int64(cl) } case http.StatusNotFound: err = ErrNotFound resp.Body.Close() return default: err = errors.New(resp.Status) resp.Body.Close() return } me.r = resp.Body me.rOff = me.off return }
// Returns -1 length if it can't determined. func instanceLength(r *http.Response) (int64, error) { switch r.StatusCode { case http.StatusOK: if h := r.Header.Get("Content-Length"); h != "" { return strconv.ParseInt(h, 10, 64) } else { return -1, nil } case http.StatusPartialContent: cr, ok := missinggo.ParseHTTPBytesContentRange(r.Header.Get("Content-Range")) if !ok { return -1, errors.New("bad 206 response") } return cr.Length, nil default: return -1, errors.New(r.Status) } }