From f6fd6ee777e14c2e75debf673ae26bfeb3861f65 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 6 May 2022 14:03:01 +0100 Subject: [PATCH] fs: fix FixRangeOption make SeekOptions into absolute RangeOptions Cloudflare R2 doesn't support range options like `Range: bytes=21-`. This patch makes FixRangeOption turn a SeekOption into an absolute RangeOption like this `Range: bytes=21-25` to interoperate with R2. See: #5642 --- fs/open_options.go | 11 ++++++++--- fs/open_options_test.go | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/fs/open_options.go b/fs/open_options.go index 268024b17..38a391fb9 100644 --- a/fs/open_options.go +++ b/fs/open_options.go @@ -138,6 +138,9 @@ func (o *RangeOption) Decode(size int64) (offset, limit int64) { // absolute fetch using the size passed in and makes sure the range does // not exceed filesize. Some remotes (e.g. Onedrive, Box) don't support // range requests which index from the end. +// +// It also adjusts any SeekOption~s, turning them into absolute +// RangeOption~s instead. func FixRangeOption(options []OpenOption, size int64) { if size == 0 { // if size 0 then remove RangeOption~s @@ -150,9 +153,9 @@ func FixRangeOption(options []OpenOption, size int64) { } return } - for i := range options { - option := options[i] - if x, ok := option.(*RangeOption); ok { + for i, option := range options { + switch x := option.(type) { + case *RangeOption: // If start is < 0 then fetch from the end if x.Start < 0 { x = &RangeOption{Start: size - x.End, End: -1} @@ -163,6 +166,8 @@ func FixRangeOption(options []OpenOption, size int64) { x = &RangeOption{Start: x.Start, End: size - 1} options[i] = x } + case *SeekOption: + options[i] = &RangeOption{Start: x.Offset, End: size - 1} } } } diff --git a/fs/open_options_test.go b/fs/open_options_test.go index 6327a8c9e..fefd1f906 100644 --- a/fs/open_options_test.go +++ b/fs/open_options_test.go @@ -207,6 +207,20 @@ func TestFixRangeOptions(t *testing.T) { }, size: 100, }, + { + name: "SeekOption", + in: []OpenOption{ + &HTTPOption{Key: "a", Value: "1"}, + &SeekOption{Offset: 10}, + &HTTPOption{Key: "b", Value: "2"}, + }, + want: []OpenOption{ + &HTTPOption{Key: "a", Value: "1"}, + &RangeOption{Start: 10, End: 99}, + &HTTPOption{Key: "b", Value: "2"}, + }, + size: 100, + }, } { FixRangeOption(test.in, test.size) assert.Equal(t, test.want, test.in, test.name)