Change default webseed path escaping to work for all S3-compatible providers

This commit is contained in:
Matt Joiner 2022-12-23 11:18:36 +11:00
parent f75989863c
commit 291c428016
No known key found for this signature in database
GPG Key ID: 6B990B8185E7F782
2 changed files with 24 additions and 61 deletions

View File

@ -24,7 +24,12 @@ func EscapePath(pathComps []string) string {
func defaultPathEscaper(pathComps []string) string { func defaultPathEscaper(pathComps []string) string {
var ret []string var ret []string
for _, comp := range pathComps { for _, comp := range pathComps {
ret = append(ret, url.QueryEscape(comp)) esc := url.PathEscape(comp)
// S3 incorrectly escapes + in paths to spaces, so we add an extra encoding for that. This
// seems to be handled correctly regardless of whether an endpoint uses query or path
// escaping.
esc = strings.ReplaceAll(esc, "+", "%2B")
ret = append(ret, esc)
} }
return path.Join(ret...) return path.Join(ret...)
} }

View File

@ -2,71 +2,29 @@ package webseed
import ( import (
"net/url" "net/url"
"path"
"testing" "testing"
qt "github.com/frankban/quicktest" qt "github.com/frankban/quicktest"
) )
func TestEscapePath(t *testing.T) { func TestDefaultPathEscaper(t *testing.T) {
c := qt.New(t) c := qt.New(t)
test := func( test := func(unescaped string, parts ...string) {
parts []string, result string, escaped := defaultPathEscaper(parts)
escaper PathEscaper, pathUnescaped, err := url.PathUnescape(escaped)
unescaper func(string) (string, error), c.Assert(err, qt.IsNil)
) { c.Assert(pathUnescaped, qt.Equals, unescaped)
unescaped, err := unescaper(escaper(parts)) queryUnescaped, err := url.QueryUnescape(escaped)
if !c.Check(err, qt.IsNil) { c.Assert(err, qt.IsNil)
return c.Assert(queryUnescaped, qt.Equals, unescaped)
} }
c.Check(unescaped, qt.Equals, result) test("a_b-c/d + e.f", "a_b-c", "d + e.f")
} test("a_1-b_c2/d 3. (e, f).g", "a_1-b_c2", "d 3. (e, f).g")
test("a_b-c/d + e.f", "a_b-c", "d + e.f")
// Test with nil escapers (always uses url.QueryEscape) test("a_1-b_c2/d 3. (e, f).g", "a_1-b_c2", "d 3. (e, f).g")
// ------ test("war/and/peace", "war", "and", "peace")
test( test("hello/world", "hello", "world")
[]string{"a_b-c", "d + e.f"}, test(`ノ┬─┬ノ ︵ ( \o°o)\`, `ノ┬─┬ノ ︵ ( \o°o)\`)
"a_b-c/d + e.f", test(`%aa + %bb/Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`,
defaultPathEscaper, `%aa + %bb`, `Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`)
url.QueryUnescape,
)
test(
[]string{"a_1-b_c2", "d 3. (e, f).g"},
"a_1-b_c2/d 3. (e, f).g",
defaultPathEscaper,
url.QueryUnescape,
)
// Test with custom escapers
// ------
test(
[]string{"a_b-c", "d + e.f"},
"a_b-c/d + e.f",
func(s []string) string {
var ret []string
for _, comp := range s {
ret = append(ret, url.PathEscape(comp))
}
return path.Join(ret...)
},
url.PathUnescape,
)
test(
[]string{"a_1-b_c2", "d 3. (e, f).g"},
"a_1-b_c2/d 3. (e, f).g",
func(s []string) string {
var ret []string
for _, comp := range s {
ret = append(ret, url.PathEscape(comp))
}
return path.Join(ret...)
},
url.PathUnescape,
)
}
func TestEscapePathForEmptyInfoName(t *testing.T) {
qt.Check(t, defaultPathEscaper([]string{`ノ┬─┬ノ ︵ ( \o°o)\`}), qt.Equals, "%E3%83%8E%E2%94%AC%E2%94%80%E2%94%AC%E3%83%8E+%EF%B8%B5+%28+%5Co%C2%B0o%29%5C")
qt.Check(t, defaultPathEscaper([]string{"hello", "world"}), qt.Equals, "hello/world")
qt.Check(t, defaultPathEscaper([]string{"war", "and", "peace"}), qt.Equals, "war/and/peace")
} }