diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 541c782d..15b2d37a 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -19,10 +19,12 @@ func ParseWithPath(path string) (*config.Config, error) { } // ApplyConfig dispatch configure to all parts -func ApplyConfig(cfg *config.Config) { +func ApplyConfig(cfg *config.Config, force bool) { + if force { + updateGeneral(cfg.General) + } updateProxies(cfg.Proxies) updateRules(cfg.Rules) - updateGeneral(cfg.General) } func GetGeneral() *config.General { diff --git a/hub/hub.go b/hub/hub.go index 4a3715e5..41e0c64a 100644 --- a/hub/hub.go +++ b/hub/hub.go @@ -16,6 +16,6 @@ func Parse() error { go route.Start(cfg.General.ExternalController, cfg.General.Secret) } - executor.ApplyConfig(cfg) + executor.ApplyConfig(cfg, true) return nil } diff --git a/hub/route/configs.go b/hub/route/configs.go index 8954f93e..45e1a99e 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -2,6 +2,7 @@ package route import ( "net/http" + "path/filepath" "github.com/Dreamacro/clash/hub/executor" "github.com/Dreamacro/clash/log" @@ -15,6 +16,7 @@ import ( func configRouter() http.Handler { r := chi.NewRouter() r.Get("/", getConfigs) + r.Put("/", updateConfigs) r.Patch("/", patchConfigs) return r } @@ -68,3 +70,33 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } + +type updateConfigRequest struct { + Path string `json:"path"` +} + +func updateConfigs(w http.ResponseWriter, r *http.Request) { + req := updateConfigRequest{} + if err := render.DecodeJSON(r.Body, &req); err != nil { + w.WriteHeader(http.StatusBadRequest) + render.Respond(w, r, ErrBadRequest) + return + } + + if !filepath.IsAbs(req.Path) { + w.WriteHeader(http.StatusBadRequest) + render.Respond(w, r, newError("path is not a absoluted path")) + return + } + + force := r.URL.Query().Get("force") == "true" + cfg, err := executor.ParseWithPath(req.Path) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + render.Respond(w, r, newError(err.Error())) + return + } + + executor.ApplyConfig(cfg, force) + w.WriteHeader(http.StatusNoContent) +} diff --git a/hub/route/server.go b/hub/route/server.go index 72fe9655..d7e5334b 100644 --- a/hub/route/server.go +++ b/hub/route/server.go @@ -47,7 +47,7 @@ func Start(addr string, secret string) { r.With(jsonContentType).Get("/logs", getLogs) r.Mount("/configs", configRouter()) r.Mount("/proxies", proxyRouter()) - // r.Mount("/rules", ruleRouter()) + r.Mount("/rules", ruleRouter()) log.Infoln("RESTful API listening at: %s", addr) err := http.ListenAndServe(addr, r)