diff --git a/cmd/serve/http/http.go b/cmd/serve/http/http.go index 9708ad9c1..ca7c76673 100644 --- a/cmd/serve/http/http.go +++ b/cmd/serve/http/http.go @@ -11,6 +11,7 @@ import ( "github.com/ncw/rclone/cmd" "github.com/ncw/rclone/fs" + "github.com/ncw/rclone/rest" "github.com/ncw/rclone/vfs" "github.com/ncw/rclone/vfs/vfsflags" "github.com/spf13/cobra" @@ -117,6 +118,22 @@ type entry struct { // entries represents a directory type entries []entry +// addEntry adds an entry to that directory +func (es *entries) addEntry(node interface { + Path() string + Name() string + IsDir() bool +}) { + remote := node.Path() + leaf := node.Name() + urlRemote := leaf + if node.IsDir() { + leaf += "/" + urlRemote += "/" + } + *es = append(*es, entry{remote: remote, URL: rest.URLPathEscape(urlRemote), Leaf: leaf}) +} + // indexPage is a directory listing template var indexPage = ` @@ -171,14 +188,7 @@ func (s *server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote stri var out entries for _, node := range dirEntries { - remote := node.Path() - leaf := node.Name() - urlRemote := leaf - if node.IsDir() { - leaf += "/" - urlRemote += "/" - } - out = append(out, entry{remote: remote, URL: urlRemote, Leaf: leaf}) + out.addEntry(node) } // Account the transfer diff --git a/cmd/serve/http/http_test.go b/cmd/serve/http/http_test.go index 8eb7fbf82..deb4ba264 100644 --- a/cmd/serve/http/http_test.go +++ b/cmd/serve/http/http_test.go @@ -1,3 +1,5 @@ +// +build go1.8 + package http import ( @@ -5,6 +7,7 @@ import ( "io/ioutil" "net" "net/http" + "path" "strings" "testing" "time" @@ -190,3 +193,33 @@ func TestGET(t *testing.T) { checkGolden(t, test.Golden, body) } } + +type mockNode struct { + path string + isdir bool +} + +func (n mockNode) Path() string { return n.path } +func (n mockNode) Name() string { + if n.path == "" { + return "" + } + return path.Base(n.path) +} +func (n mockNode) IsDir() bool { return n.isdir } + +func TestAddEntry(t *testing.T) { + var es entries + es.addEntry(mockNode{path: "", isdir: true}) + es.addEntry(mockNode{path: "dir", isdir: true}) + es.addEntry(mockNode{path: "a/b/c/d.txt", isdir: false}) + es.addEntry(mockNode{path: "a/b/c/colon:colon.txt", isdir: false}) + es.addEntry(mockNode{path: "\"quotes\".txt", isdir: false}) + assert.Equal(t, entries{ + {remote: "", URL: "/", Leaf: "/"}, + {remote: "dir", URL: "dir/", Leaf: "dir/"}, + {remote: "a/b/c/d.txt", URL: "d.txt", Leaf: "d.txt"}, + {remote: "a/b/c/colon:colon.txt", URL: "./colon:colon.txt", Leaf: "colon:colon.txt"}, + {remote: "\"quotes\".txt", URL: "%22quotes%22.txt", Leaf: "\"quotes\".txt"}, + }, es) +}