diff --git a/fs/rc/rcserver/rcserver.go b/fs/rc/rcserver/rcserver.go index 6204c4810..064348915 100644 --- a/fs/rc/rcserver/rcserver.go +++ b/fs/rc/rcserver/rcserver.go @@ -387,18 +387,20 @@ func (s *Server) handleGet(w http.ResponseWriter, r *http.Request, path string) s.serveRoot(w, r) return case s.files != nil: - pluginsMatchResult := webgui.PluginsMatch.FindStringSubmatch(path) + if s.opt.WebUI { + pluginsMatchResult := webgui.PluginsMatch.FindStringSubmatch(path) - if s.opt.WebUI && pluginsMatchResult != nil && len(pluginsMatchResult) > 2 { - ok := webgui.ServePluginOK(w, r, pluginsMatchResult) - if !ok { - r.URL.Path = fmt.Sprintf("/%s/%s/app/build/%s", pluginsMatchResult[1], pluginsMatchResult[2], pluginsMatchResult[3]) - s.pluginsHandler.ServeHTTP(w, r) + if pluginsMatchResult != nil && len(pluginsMatchResult) > 2 { + ok := webgui.ServePluginOK(w, r, pluginsMatchResult) + if !ok { + r.URL.Path = fmt.Sprintf("/%s/%s/app/build/%s", pluginsMatchResult[1], pluginsMatchResult[2], pluginsMatchResult[3]) + s.pluginsHandler.ServeHTTP(w, r) + return + } + return + } else if webgui.ServePluginWithReferrerOK(w, r, path) { return } - return - } else if s.opt.WebUI && webgui.ServePluginWithReferrerOK(w, r, path) { - return } // Serve the files r.URL.Path = "/" + path diff --git a/fs/rc/webgui/plugins.go b/fs/rc/webgui/plugins.go index fda4896df..3ebc0ede5 100644 --- a/fs/rc/webgui/plugins.go +++ b/fs/rc/webgui/plugins.go @@ -15,6 +15,8 @@ import ( "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config" + "github.com/rclone/rclone/fs/rc/rcflags" + "github.com/rclone/rclone/lib/errors" ) // PackageJSON is the structure of package.json of a plugin @@ -62,6 +64,8 @@ var ( PluginsPath string pluginsConfigPath string availablePluginsJSONPath = "availablePlugins.json" + initSuccess = false + initMutex = &sync.Mutex{} ) func init() { @@ -69,11 +73,6 @@ func init() { PluginsPath = filepath.Join(cachePath, "plugins") pluginsConfigPath = filepath.Join(PluginsPath, "config") - loadedPlugins = newPlugins(availablePluginsJSONPath) - err := loadedPlugins.readFromFile() - if err != nil { - fs.Errorf(nil, "error reading available plugins: %v", err) - } } // Plugins represents the structure how plugins are saved onto disk @@ -90,9 +89,25 @@ func newPlugins(fileName string) *Plugins { return &p } +func initPluginsOrError() error { + if !rcflags.Opt.WebUI { + return errors.New("WebUI needs to be enabled for plugins to work") + } + initMutex.Lock() + defer initMutex.Unlock() + if !initSuccess { + loadedPlugins = newPlugins(availablePluginsJSONPath) + err := loadedPlugins.readFromFile() + if err != nil { + fs.Errorf(nil, "error reading available plugins: %v", err) + } + initSuccess = true + } + + return nil +} + func (p *Plugins) readFromFile() (err error) { - //p.mutex.Lock() - //defer p.mutex.Unlock() err = CreatePathIfNotExist(pluginsConfigPath) if err != nil { return err @@ -169,8 +184,6 @@ func (p *Plugins) addTestPlugin(pluginName string, testURL string, handlesType [ } func (p *Plugins) writeToFile() (err error) { - //p.mutex.Lock() - //defer p.mutex.Unlock() availablePluginsJSON := filepath.Join(pluginsConfigPath, p.fileName) file, err := json.MarshalIndent(p, "", " ") @@ -290,6 +303,10 @@ var referrerPathReg = regexp.MustCompile("^(https?):\\/\\/(.+):([0-9]+)?\\/(.*)\ // sends a redirect to actual url. This function is useful for plugins to refer to absolute paths when // the referrer in http.Request is set func ServePluginWithReferrerOK(w http.ResponseWriter, r *http.Request, path string) (ok bool) { + err := initPluginsOrError() + if err != nil { + return false + } referrer := r.Referer() referrerPathMatch := referrerPathReg.FindStringSubmatch(referrer) diff --git a/fs/rc/webgui/rc.go b/fs/rc/webgui/rc.go index 2c8263219..37c6f69ff 100644 --- a/fs/rc/webgui/rc.go +++ b/fs/rc/webgui/rc.go @@ -30,6 +30,10 @@ Eg } func rcListTestPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error) { + err = initPluginsOrError() + if err != nil { + return nil, err + } return rc.Params{ "loadedTestPlugins": filterPlugins(loadedPlugins, func(json *PackageJSON) bool { return json.isTesting() }), }, nil @@ -54,6 +58,10 @@ Eg }) } func rcRemoveTestPlugin(_ context.Context, in rc.Params) (out rc.Params, err error) { + err = initPluginsOrError() + if err != nil { + return nil, err + } name, err := in.GetString("name") if err != nil { return nil, err @@ -85,6 +93,10 @@ Eg } func rcAddPlugin(_ context.Context, in rc.Params) (out rc.Params, err error) { + err = initPluginsOrError() + if err != nil { + return nil, err + } pluginURL, err := in.GetString("url") if err != nil { return nil, err @@ -192,6 +204,10 @@ Eg } func rcGetPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error) { + err = initPluginsOrError() + if err != nil { + return nil, err + } err = loadedPlugins.readFromFile() if err != nil { return nil, err @@ -222,6 +238,10 @@ Eg } func rcRemovePlugin(_ context.Context, in rc.Params) (out rc.Params, err error) { + err = initPluginsOrError() + if err != nil { + return nil, err + } name, err := in.GetString("name") if err != nil { return nil, err @@ -260,6 +280,10 @@ Eg } func rcGetPluginsForType(_ context.Context, in rc.Params) (out rc.Params, err error) { + err = initPluginsOrError() + if err != nil { + return nil, err + } handlesType, err := in.GetString("type") if err != nil { handlesType = "" diff --git a/fs/rc/webgui/rc_test.go b/fs/rc/webgui/rc_test.go index 82b19ec10..72de1b34b 100644 --- a/fs/rc/webgui/rc_test.go +++ b/fs/rc/webgui/rc_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/rclone/rclone/fs/rc" + "github.com/rclone/rclone/fs/rc/rcflags" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -18,6 +19,10 @@ const testPluginAuthor = "rclone" const testPluginKey = testPluginAuthor + "/" + testPluginName const testPluginURL = "https://github.com/" + testPluginAuthor + "/" + testPluginName + "/" +func init() { + rcflags.Opt.WebUI = true +} + func setCacheDir(t *testing.T) string { cacheDir, err := ioutil.TempDir("", "rclone-cache-dir") assert.Nil(t, err)