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
This commit is contained in:
Nick Craig-Wood 2022-05-06 14:03:01 +01:00
parent 1e66d052fd
commit f6fd6ee777
2 changed files with 22 additions and 3 deletions

View File

@ -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}
}
}
}

View File

@ -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)