From 5d2e327b6fbec2e821f2b9f942bbaa1fe534c021 Mon Sep 17 00:00:00 2001 From: Nolan Woods Date: Mon, 19 Apr 2021 22:14:21 -0700 Subject: [PATCH] http: Replace httplib with lib/http --- cmd/serve/http/http.go | 80 +++++++++++--------- cmd/serve/http/http_test.go | 16 ++-- cmd/serve/http/testdata/golden/indexpost.txt | 2 +- cmd/serve/http/testdata/golden/onepost.txt | 2 +- 4 files changed, 54 insertions(+), 46 deletions(-) diff --git a/cmd/serve/http/http.go b/cmd/serve/http/http.go index 3d374e6ce..ca4a071ca 100644 --- a/cmd/serve/http/http.go +++ b/cmd/serve/http/http.go @@ -1,7 +1,9 @@ package http import ( + "html/template" "io" + "log" "net/http" "os" "path" @@ -9,19 +11,34 @@ import ( "strings" "time" + "github.com/go-chi/chi/v5" "github.com/rclone/rclone/cmd" - "github.com/rclone/rclone/cmd/serve/httplib" - "github.com/rclone/rclone/cmd/serve/httplib/httpflags" + "github.com/rclone/rclone/cmd/serve/http/data" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/accounting" + httplib "github.com/rclone/rclone/lib/http" + "github.com/rclone/rclone/lib/http/auth" "github.com/rclone/rclone/lib/http/serve" "github.com/rclone/rclone/vfs" "github.com/rclone/rclone/vfs/vfsflags" "github.com/spf13/cobra" ) +// Options required for http server +type Options struct { + data.Options +} + +// DefaultOpt is the default values used for Options +var DefaultOpt = Options{} + +// Opt is options set by command line flags +var Opt = DefaultOpt + func init() { - httpflags.AddFlags(Command.Flags()) + data.AddFlags(Command.Flags(), "", &Opt.Options) + httplib.AddFlags(Command.Flags()) + auth.AddFlags(Command.Flags()) vfsflags.AddFlags(Command.Flags()) } @@ -40,17 +57,17 @@ The server will log errors. Use -v to see access logs. --bwlimit will be respected for file transfers. Use --stats to control the stats printing. -` + httplib.Help + vfs.Help, +` + httplib.Help + data.Help + auth.Help + vfs.Help, Run: func(command *cobra.Command, args []string) { cmd.CheckArgs(1, 1, command, args) f := cmd.NewFsSrc(args) cmd.Run(false, true, command, func() error { - s := newServer(f, &httpflags.Opt) - err := s.Serve() + s := newServer(f, Opt.Template) + router, err := httplib.Router() if err != nil { return err } - s.Wait() + s.Bind("/*", router) return nil }) }, @@ -58,49 +75,38 @@ control the stats printing. // server contains everything to run the server type server struct { - *httplib.Server - f fs.Fs - vfs *vfs.VFS + f fs.Fs + vfs *vfs.VFS + HTMLTemplate *template.Template // HTML template for web interface } -func newServer(f fs.Fs, opt *httplib.Options) *server { - mux := http.NewServeMux() - s := &server{ - Server: httplib.NewServer(mux, opt), - f: f, - vfs: vfs.New(f, &vfsflags.Opt), +func newServer(f fs.Fs, templatePath string) *server { + htmlTemplate, templateErr := data.GetTemplate(templatePath) + if templateErr != nil { + log.Fatalf(templateErr.Error()) + } + s := &server{ + f: f, + vfs: vfs.New(f, &vfsflags.Opt), + HTMLTemplate: htmlTemplate, } - mux.HandleFunc(s.Opt.BaseURL+"/", s.handler) return s } -// Serve runs the http server in the background. -// -// Use s.Close() and s.Wait() to shutdown server -func (s *server) Serve() error { - err := s.Server.Serve() - if err != nil { - return err - } - fs.Logf(s.f, "Serving on %s", s.URL()) - return nil +func (s *server) Bind(pattern string, router chi.Router) { + router.Get(pattern, s.handler) + router.Head(pattern, s.handler) } // 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 - } w.Header().Set("Accept-Ranges", "bytes") w.Header().Set("Server", "rclone/"+fs.Version) - urlPath, ok := s.Path(w, r) - if !ok { - return - } - isDir := strings.HasSuffix(urlPath, "/") - remote := strings.Trim(urlPath, "/") + //rctx := chi.RouteContext(r.Context()) + + isDir := strings.HasSuffix(r.URL.Path, "/") + remote := strings.Trim(r.URL.Path, "/") if isDir { s.serveDir(w, r, remote) } else { diff --git a/cmd/serve/http/http_test.go b/cmd/serve/http/http_test.go index c429febc7..311bac70b 100644 --- a/cmd/serve/http/http_test.go +++ b/cmd/serve/http/http_test.go @@ -10,10 +10,10 @@ import ( "time" _ "github.com/rclone/rclone/backend/local" - "github.com/rclone/rclone/cmd/serve/httplib" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config/configfile" "github.com/rclone/rclone/fs/filter" + httplib "github.com/rclone/rclone/lib/http" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -32,10 +32,13 @@ const ( func startServer(t *testing.T, f fs.Fs) { opt := httplib.DefaultOpt opt.ListenAddr = testBindAddress - opt.Template = testTemplate - httpServer = newServer(f, &opt) - assert.NoError(t, httpServer.Serve()) - testURL = httpServer.Server.URL() + httpServer = newServer(f, testTemplate) + router, err := httplib.Router() + if err != nil { + t.Fatal(err.Error()) + } + httpServer.Bind("/*", router) + testURL = httplib.URL() // try to connect to the test server pause := time.Millisecond @@ -227,6 +230,5 @@ func TestGET(t *testing.T) { } func TestFinalise(t *testing.T) { - httpServer.Close() - httpServer.Wait() + _ = httplib.Shutdown() } diff --git a/cmd/serve/http/testdata/golden/indexpost.txt b/cmd/serve/http/testdata/golden/indexpost.txt index 85a67dcae..b14e2a41b 100644 --- a/cmd/serve/http/testdata/golden/indexpost.txt +++ b/cmd/serve/http/testdata/golden/indexpost.txt @@ -1 +1 @@ -Method not allowed +Method Not Allowed diff --git a/cmd/serve/http/testdata/golden/onepost.txt b/cmd/serve/http/testdata/golden/onepost.txt index 85a67dcae..b14e2a41b 100644 --- a/cmd/serve/http/testdata/golden/onepost.txt +++ b/cmd/serve/http/testdata/golden/onepost.txt @@ -1 +1 @@ -Method not allowed +Method Not Allowed