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 := httptoo.ParseBytesContentRange(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 }
// ok is false if the response just doesn't specify anything we handle. func instanceLength(r *http.Response) (l int64, err error) { switch r.StatusCode { case http.StatusOK: l, err = strconv.ParseInt(r.Header.Get("Content-Length"), 10, 64) return case http.StatusPartialContent: cr, parseOk := httptoo.ParseBytesContentRange(r.Header.Get("Content-Range")) l = cr.Length if !parseOk { err = errors.New("error parsing Content-Range") } return default: err = errors.New("unhandled status code") return } }