forked from TrueCloudLab/rclone
serve webdav: fix serveDir not being updated with changes from webdav
Fixes an issue where changes such as renaming done using webdav would not be reflected in the html directory listing
This commit is contained in:
parent
5597d6d871
commit
6e8e620e71
3 changed files with 55 additions and 25 deletions
|
@ -43,7 +43,7 @@ control the stats printing.
|
||||||
cmd.CheckArgs(1, 1, command, args)
|
cmd.CheckArgs(1, 1, command, args)
|
||||||
f := cmd.NewFsSrc(args)
|
f := cmd.NewFsSrc(args)
|
||||||
cmd.Run(false, true, command, func() error {
|
cmd.Run(false, true, command, func() error {
|
||||||
s := NewServer(f, &httpflags.Opt)
|
s := newServer(f, &httpflags.Opt)
|
||||||
err := s.Serve()
|
err := s.Serve()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -54,29 +54,28 @@ control the stats printing.
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server contains everything to run the Server
|
// server contains everything to run the server
|
||||||
type Server struct {
|
type server struct {
|
||||||
*httplib.Server
|
*httplib.Server
|
||||||
f fs.Fs
|
f fs.Fs
|
||||||
vfs *vfs.VFS
|
vfs *vfs.VFS
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new http server
|
func newServer(f fs.Fs, opt *httplib.Options) *server {
|
||||||
func NewServer(f fs.Fs, opt *httplib.Options) *Server {
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
s := &Server{
|
s := &server{
|
||||||
Server: httplib.NewServer(mux, opt),
|
Server: httplib.NewServer(mux, opt),
|
||||||
f: f,
|
f: f,
|
||||||
vfs: vfs.New(f, &vfsflags.Opt),
|
vfs: vfs.New(f, &vfsflags.Opt),
|
||||||
}
|
}
|
||||||
mux.HandleFunc("/", s.Handler)
|
mux.HandleFunc("/", s.handler)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve runs the http Server in the background.
|
// Serve runs the http server in the background.
|
||||||
//
|
//
|
||||||
// Use s.Close() and s.Wait() to shutdown Server
|
// Use s.Close() and s.Wait() to shutdown server
|
||||||
func (s *Server) Serve() error {
|
func (s *server) Serve() error {
|
||||||
err := s.Server.Serve()
|
err := s.Server.Serve()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -85,8 +84,8 @@ func (s *Server) Serve() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler reads incoming requests and dispatches them
|
// handler reads incoming requests and dispatches them
|
||||||
func (s *Server) Handler(w http.ResponseWriter, r *http.Request) {
|
func (s *server) handler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != "GET" && r.Method != "HEAD" {
|
if r.Method != "GET" && r.Method != "HEAD" {
|
||||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
|
@ -105,7 +104,7 @@ func (s *Server) Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveDir serves a directory index at dirRemote
|
// serveDir serves a directory index at dirRemote
|
||||||
func (s *Server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote string) {
|
func (s *server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote string) {
|
||||||
// List the directory
|
// List the directory
|
||||||
node, err := s.vfs.Stat(dirRemote)
|
node, err := s.vfs.Stat(dirRemote)
|
||||||
if err == vfs.ENOENT {
|
if err == vfs.ENOENT {
|
||||||
|
@ -136,7 +135,7 @@ func (s *Server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote stri
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveFile serves a file object at remote
|
// serveFile serves a file object at remote
|
||||||
func (s *Server) serveFile(w http.ResponseWriter, r *http.Request, remote string) {
|
func (s *server) serveFile(w http.ResponseWriter, r *http.Request, remote string) {
|
||||||
node, err := s.vfs.Stat(remote)
|
node, err := s.vfs.Stat(remote)
|
||||||
if err == vfs.ENOENT {
|
if err == vfs.ENOENT {
|
||||||
fs.Infof(remote, "%s: File not found", r.RemoteAddr)
|
fs.Infof(remote, "%s: File not found", r.RemoteAddr)
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
updateGolden = flag.Bool("updategolden", false, "update golden files for regression test")
|
updateGolden = flag.Bool("updategolden", false, "update golden files for regression test")
|
||||||
httpServer *Server
|
httpServer *server
|
||||||
testURL string
|
testURL string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ const (
|
||||||
func startServer(t *testing.T, f fs.Fs) {
|
func startServer(t *testing.T, f fs.Fs) {
|
||||||
opt := httplib.DefaultOpt
|
opt := httplib.DefaultOpt
|
||||||
opt.ListenAddr = testBindAddress
|
opt.ListenAddr = testBindAddress
|
||||||
httpServer = NewServer(f, &opt)
|
httpServer = newServer(f, &opt)
|
||||||
assert.NoError(t, httpServer.Serve())
|
assert.NoError(t, httpServer.Serve())
|
||||||
testURL = httpServer.Server.URL()
|
testURL = httpServer.Server.URL()
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ncw/rclone/cmd"
|
"github.com/ncw/rclone/cmd"
|
||||||
rhttp "github.com/ncw/rclone/cmd/serve/http"
|
|
||||||
"github.com/ncw/rclone/cmd/serve/httplib"
|
"github.com/ncw/rclone/cmd/serve/httplib"
|
||||||
"github.com/ncw/rclone/cmd/serve/httplib/httpflags"
|
"github.com/ncw/rclone/cmd/serve/httplib/httpflags"
|
||||||
|
"github.com/ncw/rclone/cmd/serve/httplib/serve"
|
||||||
"github.com/ncw/rclone/fs"
|
"github.com/ncw/rclone/fs"
|
||||||
"github.com/ncw/rclone/fs/hash"
|
"github.com/ncw/rclone/fs/hash"
|
||||||
"github.com/ncw/rclone/fs/log"
|
"github.com/ncw/rclone/fs/log"
|
||||||
|
@ -41,8 +41,8 @@ var Command = &cobra.Command{
|
||||||
Long: `
|
Long: `
|
||||||
rclone serve webdav implements a basic webdav server to serve the
|
rclone serve webdav implements a basic webdav server to serve the
|
||||||
remote over HTTP via the webdav protocol. This can be viewed with a
|
remote over HTTP via the webdav protocol. This can be viewed with a
|
||||||
webdav client or you can make a remote of type webdav to read and
|
webdav client, through a web browser, or you can make a remote of
|
||||||
write it.
|
type webdav to read and write it.
|
||||||
|
|
||||||
### Webdav options
|
### Webdav options
|
||||||
|
|
||||||
|
@ -103,7 +103,6 @@ type WebDAV struct {
|
||||||
f fs.Fs
|
f fs.Fs
|
||||||
vfs *vfs.VFS
|
vfs *vfs.VFS
|
||||||
webdavhandler *webdav.Handler
|
webdavhandler *webdav.Handler
|
||||||
httpserver *rhttp.Server
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check interface
|
// check interface
|
||||||
|
@ -121,21 +120,53 @@ func newWebDAV(f fs.Fs, opt *httplib.Options) *WebDAV {
|
||||||
Logger: w.logRequest, // FIXME
|
Logger: w.logRequest, // FIXME
|
||||||
}
|
}
|
||||||
w.webdavhandler = webdavHandler
|
w.webdavhandler = webdavHandler
|
||||||
if !disableGETDir {
|
|
||||||
w.httpserver = rhttp.NewServer(f, opt)
|
|
||||||
}
|
|
||||||
w.Server = httplib.NewServer(http.HandlerFunc(w.handler), opt)
|
w.Server = httplib.NewServer(http.HandlerFunc(w.handler), opt)
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WebDAV) handler(rw http.ResponseWriter, r *http.Request) {
|
func (w *WebDAV) handler(rw http.ResponseWriter, r *http.Request) {
|
||||||
if !disableGETDir && (r.Method == "GET" || r.Method == "HEAD") && strings.HasSuffix(r.URL.Path, "/") {
|
urlPath := r.URL.Path
|
||||||
w.httpserver.Handler(rw, r)
|
isDir := strings.HasSuffix(urlPath, "/")
|
||||||
|
remote := strings.Trim(urlPath, "/")
|
||||||
|
if !disableGETDir && (r.Method == "GET" || r.Method == "HEAD") && isDir {
|
||||||
|
w.serveDir(rw, r, remote)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.webdavhandler.ServeHTTP(rw, r)
|
w.webdavhandler.ServeHTTP(rw, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// serveDir serves a directory index at dirRemote
|
||||||
|
// This is similar to serveDir in serve http.
|
||||||
|
func (w *WebDAV) serveDir(rw http.ResponseWriter, r *http.Request, dirRemote string) {
|
||||||
|
// List the directory
|
||||||
|
node, err := w.vfs.Stat(dirRemote)
|
||||||
|
if err == vfs.ENOENT {
|
||||||
|
http.Error(rw, "Directory not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
serve.Error(dirRemote, rw, "Failed to list directory", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !node.IsDir() {
|
||||||
|
http.Error(rw, "Not a directory", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dir := node.(*vfs.Dir)
|
||||||
|
dirEntries, err := dir.ReadDirAll()
|
||||||
|
if err != nil {
|
||||||
|
serve.Error(dirRemote, rw, "Failed to list directory", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the entries for display
|
||||||
|
directory := serve.NewDirectory(dirRemote, w.HTMLTemplate)
|
||||||
|
for _, node := range dirEntries {
|
||||||
|
directory.AddEntry(node.Path(), node.IsDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
directory.Serve(rw, r)
|
||||||
|
}
|
||||||
|
|
||||||
// serve runs the http server in the background.
|
// serve runs the http server in the background.
|
||||||
//
|
//
|
||||||
// Use s.Close() and s.Wait() to shutdown server
|
// Use s.Close() and s.Wait() to shutdown server
|
||||||
|
|
Loading…
Add table
Reference in a new issue