http: Fix directories with : in #1555

This commit is contained in:
Nick Craig-Wood 2017-07-31 23:15:31 +01:00
parent b0fd187cba
commit 2b5ce6ef51
3 changed files with 66 additions and 7 deletions

View file

@ -71,6 +71,13 @@ func urlJoin(base *url.URL, path string) (*url.URL, error) {
return base.ResolveReference(rel), nil return base.ResolveReference(rel), nil
} }
// urlEscape escapes URL path the in string using URL escaping rules
func urlEscape(in string) string {
var u url.URL
u.Path = in
return u.String()
}
// statusError returns an error if the res contained an error // statusError returns an error if the res contained an error
func statusError(res *http.Response, err error) error { func statusError(res *http.Response, err error) error {
if err != nil { if err != nil {
@ -96,11 +103,10 @@ func NewFs(name, root string) (fs.Fs, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
rootURL, err := url.Parse(root) u, err := urlJoin(base, urlEscape(root))
if err != nil { if err != nil {
return nil, err return nil, err
} }
u := base.ResolveReference(rootURL)
client := fs.Config.Client() client := fs.Config.Client()

View file

@ -118,10 +118,10 @@ func TestNewObject(t *testing.T) {
f, tidy := prepare(t) f, tidy := prepare(t)
defer tidy() defer tidy()
o, err := f.NewObject("four/underfour.txt") o, err := f.NewObject("four/under four.txt")
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "four/underfour.txt", o.Remote()) assert.Equal(t, "four/under four.txt", o.Remote())
assert.Equal(t, int64(9), o.Size()) assert.Equal(t, int64(9), o.Size())
_, ok := o.(*Object) _, ok := o.(*Object)
assert.True(t, ok) assert.True(t, ok)
@ -130,7 +130,7 @@ func TestNewObject(t *testing.T) {
tObj := o.ModTime() tObj := o.ModTime()
fi, err := os.Stat(filepath.Join(filesPath, "four", "underfour.txt")) fi, err := os.Stat(filepath.Join(filesPath, "four", "under four.txt"))
require.NoError(t, err) require.NoError(t, err)
tFile := fi.ModTime() tFile := fi.ModTime()
@ -142,7 +142,7 @@ func TestOpen(t *testing.T) {
f, tidy := prepare(t) f, tidy := prepare(t)
defer tidy() defer tidy()
o, err := f.NewObject("four/underfour.txt") o, err := f.NewObject("four/under four.txt")
require.NoError(t, err) require.NoError(t, err)
// Test normal read // Test normal read
@ -164,7 +164,7 @@ func TestMimeType(t *testing.T) {
f, tidy := prepare(t) f, tidy := prepare(t)
defer tidy() defer tidy()
o, err := f.NewObject("four/underfour.txt") o, err := f.NewObject("four/under four.txt")
require.NoError(t, err) require.NoError(t, err)
do, ok := o.(fs.MimeTyper) do, ok := o.(fs.MimeTyper)
@ -203,6 +203,57 @@ func TestIsAFileSubDir(t *testing.T) {
assert.True(t, ok) assert.True(t, ok)
} }
func TestURLJoin(t *testing.T) {
for i, test := range []struct {
base string
path string
wantOK bool
want string
}{
{"http://example.com/", "potato", true, "http://example.com/potato"},
{"http://example.com/dir/", "potato", true, "http://example.com/dir/potato"},
{"http://example.com/dir/", "../dir/potato", true, "http://example.com/dir/potato"},
{"http://example.com/dir/", "..", true, "http://example.com/"},
{"http://example.com/dir/", "http://example.com/", true, "http://example.com/"},
{"http://example.com/dir/", "http://example.com/dir/", true, "http://example.com/dir/"},
{"http://example.com/dir/", "http://example.com/dir/potato", true, "http://example.com/dir/potato"},
{"http://example.com/dir/", "/dir/", true, "http://example.com/dir/"},
{"http://example.com/dir/", "/dir/potato", true, "http://example.com/dir/potato"},
{"http://example.com/dir/", "subdir/potato", true, "http://example.com/dir/subdir/potato"},
{"http://example.com/dir/", "With percent %25.txt", true, "http://example.com/dir/With%20percent%20%25.txt"},
{"http://example.com/dir/", "With colon :", false, ""},
{"http://example.com/dir/", urlEscape("With colon :"), true, "http://example.com/dir/With%20colon%20:"},
} {
u, err := url.Parse(test.base)
require.NoError(t, err)
got, err := urlJoin(u, test.path)
gotOK := err == nil
what := fmt.Sprintf("test %d base=%q, val=%q", i, test.base, test.path)
assert.Equal(t, test.wantOK, gotOK, what)
var gotString string
if gotOK {
gotString = got.String()
}
assert.Equal(t, test.want, gotString, what)
}
}
func TestURLEscape(t *testing.T) {
for i, test := range []struct {
path string
want string
}{
{"", ""},
{"/hello.txt", "/hello.txt"},
{"With Space", "With%20Space"},
{"With Colon:", "./With%20Colon:"},
{"With Percent%", "With%20Percent%25"},
} {
got := urlEscape(test.path)
assert.Equal(t, test.want, got, fmt.Sprintf("Test %d path = %q", i, test.path))
}
}
func TestParseName(t *testing.T) { func TestParseName(t *testing.T) {
for i, test := range []struct { for i, test := range []struct {
base string base string
@ -221,6 +272,8 @@ func TestParseName(t *testing.T) {
{"http://example.com/dir/", "/dir/potato", true, "potato"}, {"http://example.com/dir/", "/dir/potato", true, "potato"},
{"http://example.com/dir/", "subdir/potato", false, ""}, {"http://example.com/dir/", "subdir/potato", false, ""},
{"http://example.com/dir/", "With percent %25.txt", true, "With percent %.txt"}, {"http://example.com/dir/", "With percent %25.txt", true, "With percent %.txt"},
{"http://example.com/dir/", "With colon :", false, ""},
{"http://example.com/dir/", urlEscape("With colon :"), true, "With colon :"},
} { } {
u, err := url.Parse(test.base) u, err := url.Parse(test.base)
require.NoError(t, err) require.NoError(t, err)