From 622e0d19ce325e6077cb2ed77b7b56db955ec295 Mon Sep 17 00:00:00 2001 From: Gary Kim Date: Wed, 12 Jun 2019 16:50:56 +0800 Subject: [PATCH] serve webdav: combine serve webdav and serve http --- cmd/serve/http/http.go | 27 ++++++++++++++------------- cmd/serve/http/http_test.go | 4 ++-- cmd/serve/webdav/webdav.go | 28 ++++++++++++++++++++++------ 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/cmd/serve/http/http.go b/cmd/serve/http/http.go index c10019480..f199c9fce 100644 --- a/cmd/serve/http/http.go +++ b/cmd/serve/http/http.go @@ -43,7 +43,7 @@ control the stats printing. cmd.CheckArgs(1, 1, command, args) f := cmd.NewFsSrc(args) cmd.Run(false, true, command, func() error { - s := newServer(f, &httpflags.Opt) + s := NewServer(f, &httpflags.Opt) err := s.Serve() if err != nil { return err @@ -54,28 +54,29 @@ control the stats printing. }, } -// server contains everything to run the server -type server struct { +// Server contains everything to run the Server +type Server struct { *httplib.Server f fs.Fs vfs *vfs.VFS } -func newServer(f fs.Fs, opt *httplib.Options) *server { +// NewServer creates a new http server +func NewServer(f fs.Fs, opt *httplib.Options) *Server { mux := http.NewServeMux() - s := &server{ + s := &Server{ Server: httplib.NewServer(mux, opt), f: f, vfs: vfs.New(f, &vfsflags.Opt), } - mux.HandleFunc("/", s.handler) + mux.HandleFunc("/", s.Handler) 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 -func (s *server) Serve() error { +// Use s.Close() and s.Wait() to shutdown Server +func (s *Server) Serve() error { err := s.Server.Serve() if err != nil { return err @@ -84,8 +85,8 @@ func (s *server) Serve() error { return nil } -// handler reads incoming requests and dispatches them -func (s *server) handler(w http.ResponseWriter, r *http.Request) { +// Handler reads incoming requests and dispatches them +func (s *Server) Handler(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" && r.Method != "HEAD" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return @@ -104,7 +105,7 @@ func (s *server) handler(w http.ResponseWriter, r *http.Request) { } // 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 node, err := s.vfs.Stat(dirRemote) if err == vfs.ENOENT { @@ -135,7 +136,7 @@ func (s *server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote stri } // 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) if err == vfs.ENOENT { fs.Infof(remote, "%s: File not found", r.RemoteAddr) diff --git a/cmd/serve/http/http_test.go b/cmd/serve/http/http_test.go index e43aeed3b..d6616f5e1 100644 --- a/cmd/serve/http/http_test.go +++ b/cmd/serve/http/http_test.go @@ -19,7 +19,7 @@ import ( var ( updateGolden = flag.Bool("updategolden", false, "update golden files for regression test") - httpServer *server + httpServer *Server testURL string ) @@ -30,7 +30,7 @@ const ( func startServer(t *testing.T, f fs.Fs) { opt := httplib.DefaultOpt opt.ListenAddr = testBindAddress - httpServer = newServer(f, &opt) + httpServer = NewServer(f, &opt) assert.NoError(t, httpServer.Serve()) testURL = httpServer.Server.URL() diff --git a/cmd/serve/webdav/webdav.go b/cmd/serve/webdav/webdav.go index b039f73f5..6f4416e7f 100644 --- a/cmd/serve/webdav/webdav.go +++ b/cmd/serve/webdav/webdav.go @@ -6,8 +6,10 @@ import ( "context" "net/http" "os" + "strings" "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/httpflags" "github.com/ncw/rclone/fs" @@ -22,12 +24,14 @@ import ( var ( hashName string hashType = hash.None + disableGETDir = false ) func init() { httpflags.AddFlags(Command.Flags()) vfsflags.AddFlags(Command.Flags()) Command.Flags().StringVar(&hashName, "etag-hash", "", "Which hash to use for the ETag, or auto or blank for off") + Command.Flags().BoolVar(&disableGETDir, "disable-dir-list", false, "Disable HTML directory list on GET request for a directory") } // Command definition for cobra @@ -96,8 +100,10 @@ Use "rclone hashsum" to see the full list. // overwriting another existing file or directory is an error is OS-dependent. type WebDAV struct { *httplib.Server - f fs.Fs - vfs *vfs.VFS + f fs.Fs + vfs *vfs.VFS + webdavhandler *webdav.Handler + httpserver *rhttp.Server } // check interface @@ -109,17 +115,27 @@ func newWebDAV(f fs.Fs, opt *httplib.Options) *WebDAV { f: f, vfs: vfs.New(f, &vfsflags.Opt), } - - handler := &webdav.Handler{ + webdavHandler := &webdav.Handler{ FileSystem: w, LockSystem: webdav.NewMemLS(), Logger: w.logRequest, // FIXME } - - w.Server = httplib.NewServer(handler, opt) + w.webdavhandler = webdavHandler + if !disableGETDir { + w.httpserver = rhttp.NewServer(f, opt) + } + w.Server = httplib.NewServer(http.HandlerFunc(w.handler), opt) return w } +func (w *WebDAV) handler(rw http.ResponseWriter, r *http.Request) { + if !disableGETDir && (r.Method == "GET" || r.Method == "HEAD") && strings.HasSuffix(r.URL.Path, "/") { + w.httpserver.Handler(rw, r) + return + } + w.webdavhandler.ServeHTTP(rw, r) +} + // serve runs the http server in the background. // // Use s.Close() and s.Wait() to shutdown server