diff --git a/backend/mailru/mailru.go b/backend/mailru/mailru.go index e35c4e334..aeea7bc64 100644 --- a/backend/mailru/mailru.go +++ b/backend/mailru/mailru.go @@ -37,6 +37,7 @@ import ( "github.com/rclone/rclone/lib/encoder" "github.com/rclone/rclone/lib/oauthutil" "github.com/rclone/rclone/lib/pacer" + "github.com/rclone/rclone/lib/readers" "github.com/rclone/rclone/lib/rest" "github.com/pkg/errors" @@ -2116,7 +2117,18 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read return nil, err } - start, end, partial := getTransferRange(o.size, options...) + start, end, partialRequest := getTransferRange(o.size, options...) + + headers := map[string]string{ + "Accept": "*/*", + "Content-Type": "application/octet-stream", + } + if partialRequest { + rangeStr := fmt.Sprintf("bytes=%d-%d", start, end-1) + headers["Range"] = rangeStr + // headers["Content-Range"] = rangeStr + headers["Accept-Ranges"] = "bytes" + } // TODO: set custom timeouts opts := rest.Opts{ @@ -2127,10 +2139,7 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read "client_id": {api.OAuthClientID}, "token": {token}, }, - ExtraHeaders: map[string]string{ - "Accept": "*/*", - "Range": fmt.Sprintf("bytes=%d-%d", start, end-1), - }, + ExtraHeaders: headers, } var res *http.Response @@ -2151,18 +2160,36 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read return nil, err } - var hasher gohash.Hash - if !partial { + // Server should respond with Status 206 and Content-Range header to a range + // request. Status 200 (and no Content-Range) means a full-content response. + partialResponse := res.StatusCode == 206 + + var ( + hasher gohash.Hash + wrapStream io.ReadCloser + ) + if !partialResponse { // Cannot check hash of partial download hasher = mrhash.New() } - wrapStream := &endHandler{ + wrapStream = &endHandler{ ctx: ctx, stream: res.Body, hasher: hasher, o: o, server: server, } + if partialRequest && !partialResponse { + fs.Debugf(o, "Server returned full content instead of range") + if start > 0 { + // Discard the beginning of the data + _, err = io.CopyN(ioutil.Discard, wrapStream, start) + if err != nil { + return nil, err + } + } + wrapStream = readers.NewLimitedReadCloser(wrapStream, end-start) + } return wrapStream, nil }