Browse Source
Remove duplicate slashes in object path to prevent 500 errors (#3442)
pull/3444/head
Andrey Triumfov
2 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with
70 additions and
1 deletions
-
weed/s3api/s3api_object_handlers.go
-
weed/s3api/s3api_object_handlers_test.go
|
|
@ -130,9 +130,30 @@ func urlPathEscape(object string) string { |
|
|
|
return strings.Join(escapedParts, "/") |
|
|
|
} |
|
|
|
|
|
|
|
func removeDuplicateSlashes(object string) string { |
|
|
|
result := strings.Builder{} |
|
|
|
result.Grow(len(object)) |
|
|
|
|
|
|
|
isLastSlash := false |
|
|
|
for _, r := range object { |
|
|
|
switch r { |
|
|
|
case '/': |
|
|
|
if !isLastSlash { |
|
|
|
result.WriteRune(r) |
|
|
|
} |
|
|
|
isLastSlash = true |
|
|
|
default: |
|
|
|
result.WriteRune(r) |
|
|
|
isLastSlash = false |
|
|
|
} |
|
|
|
} |
|
|
|
return result.String() |
|
|
|
} |
|
|
|
|
|
|
|
func (s3a *S3ApiServer) toFilerUrl(bucket, object string) string { |
|
|
|
object = urlPathEscape(removeDuplicateSlashes(object)) |
|
|
|
destUrl := fmt.Sprintf("http://%s%s/%s%s", |
|
|
|
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, bucket, urlPathEscape(object)) |
|
|
|
s3a.option.Filer.ToHttpAddress(), s3a.option.BucketsPath, bucket, object) |
|
|
|
return destUrl |
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -0,0 +1,48 @@ |
|
|
|
package s3api |
|
|
|
|
|
|
|
import ( |
|
|
|
"testing" |
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert" |
|
|
|
) |
|
|
|
|
|
|
|
func TestRemoveDuplicateSlashes(t *testing.T) { |
|
|
|
tests := []struct { |
|
|
|
name string |
|
|
|
path string |
|
|
|
expectedResult string |
|
|
|
}{ |
|
|
|
{ |
|
|
|
name: "empty", |
|
|
|
path: "", |
|
|
|
expectedResult: "", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "slash", |
|
|
|
path: "/", |
|
|
|
expectedResult: "/", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "object", |
|
|
|
path: "object", |
|
|
|
expectedResult: "object", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "correct path", |
|
|
|
path: "/path/to/object", |
|
|
|
expectedResult: "/path/to/object", |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "path with duplicates", |
|
|
|
path: "///path//to/object//", |
|
|
|
expectedResult: "/path/to/object/", |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
for _, tst := range tests { |
|
|
|
t.Run(tst.name, func(t *testing.T) { |
|
|
|
obj := removeDuplicateSlashes(tst.path) |
|
|
|
assert.Equal(t, tst.expectedResult, obj) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |