diff --git a/internal/stream/util.go b/internal/stream/util.go index eda611f7..2cb13daa 100644 --- a/internal/stream/util.go +++ b/internal/stream/util.go @@ -43,7 +43,7 @@ func GetRangeReadCloserFromLink(size int64, link *model.Link) (model.RangeReadCl return nil, fmt.Errorf("http request failure,status: %d err:%s", response.StatusCode, err) } if r.Start == 0 && (r.Length == -1 || r.Length == size) || response.StatusCode == http.StatusPartialContent || - checkContentRange(&response.Header, size, r.Start) { + checkContentRange(&response.Header, r.Start) { return response.Body, nil } else if response.StatusCode == http.StatusOK { log.Warnf("remote http server not supporting range request, expect low perfromace!") @@ -72,12 +72,12 @@ func RequestRangedHttp(ctx context.Context, link *model.Link, offset, length int } // 139 cloud does not properly return 206 http status code, add a hack here -func checkContentRange(header *http.Header, size, offset int64) bool { - r, err2 := http_range.ParseRange(header.Get("Content-Range"), size) - if err2 != nil { - log.Warnf("exception trying to parse Content-Range, will ignore,err=%s", err2) +func checkContentRange(header *http.Header, offset int64) bool { + start, _, err := http_range.ParseContentRange(header.Get("Content-Range")) + if err != nil { + log.Warnf("exception trying to parse Content-Range, will ignore,err=%s", err) } - if len(r) == 1 && r[0].Start == offset { + if start == offset { return true } return false diff --git a/pkg/http_range/range.go b/pkg/http_range/range.go index 6a5451a1..5edd210d 100644 --- a/pkg/http_range/range.go +++ b/pkg/http_range/range.go @@ -107,6 +107,27 @@ func ParseRange(s string, size int64) ([]Range, error) { // nolint:gocognit return ranges, nil } +// ParseContentRange this function parse content-range in http response +func ParseContentRange(s string) (start, end int64, err error) { + if s == "" { + return 0, 0, ErrInvalid + } + const b = "bytes " + if !strings.HasPrefix(s, b) { + return 0, 0, ErrInvalid + } + p1 := strings.Index(s, "-") + p2 := strings.Index(s, "/") + if p1 < 0 || p2 < 0 { + return 0, 0, ErrInvalid + } + startStr, endStr := textproto.TrimString(s[len(b):p1]), textproto.TrimString(s[p1+1:p2]) + start, startErr := strconv.ParseInt(startStr, 10, 64) + end, endErr := strconv.ParseInt(endStr, 10, 64) + + return start, end, errors.Join(startErr, endErr) +} + func (r Range) MimeHeader(contentType string, size int64) textproto.MIMEHeader { return textproto.MIMEHeader{ "Content-Range": {r.ContentRange(size)},