diff --git a/hub/hub.go b/hub/hub.go index d439d32e..04662a7b 100644 --- a/hub/hub.go +++ b/hub/hub.go @@ -64,8 +64,16 @@ func applyRoute(cfg *config.Config) { } // Parse call at the beginning of mihomo -func Parse(options ...Option) error { - cfg, err := executor.Parse() +func Parse(configBytes []byte, options ...Option) error { + var cfg *config.Config + var err error + + if len(configBytes) != 0 { + cfg, err = executor.ParseWithBytes(configBytes) + } else { + cfg, err = executor.Parse() + } + if err != nil { return err } diff --git a/main.go b/main.go index c7a7acbc..26f1d2c0 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/base64" "flag" "fmt" "os" @@ -28,6 +29,8 @@ var ( geodataMode bool homeDir string configFile string + configString string + configBytes []byte externalUI string externalController string externalControllerUnix string @@ -37,6 +40,7 @@ var ( func init() { flag.StringVar(&homeDir, "d", os.Getenv("CLASH_HOME_DIR"), "set configuration directory") flag.StringVar(&configFile, "f", os.Getenv("CLASH_CONFIG_FILE"), "specify configuration file") + flag.StringVar(&configString, "config", os.Getenv("CLASH_CONFIG_STRING"), "specify base64-encoded configuration string") flag.StringVar(&externalUI, "ext-ui", os.Getenv("CLASH_OVERRIDE_EXTERNAL_UI_DIR"), "override external ui directory") flag.StringVar(&externalController, "ext-ctl", os.Getenv("CLASH_OVERRIDE_EXTERNAL_CONTROLLER"), "override external controller address") flag.StringVar(&externalControllerUnix, "ext-ctl-unix", os.Getenv("CLASH_OVERRIDE_EXTERNAL_CONTROLLER_UNIX"), "override external controller unix address") @@ -73,29 +77,46 @@ func main() { C.SetHomeDir(homeDir) } - if configFile != "" { - if !filepath.IsAbs(configFile) { - currentDir, _ := os.Getwd() - configFile = filepath.Join(currentDir, configFile) - } - } else { - configFile = filepath.Join(C.Path.HomeDir(), C.Path.Config()) - } - C.SetConfig(configFile) - if geodataMode { C.GeodataMode = true } - if err := config.Init(C.Path.HomeDir()); err != nil { - log.Fatalln("Initial configuration directory error: %s", err.Error()) + if configString != "" { + var err error + configBytes, err = base64.StdEncoding.DecodeString(configString) + if err != nil { + log.Fatalln("Initial configuration error: %s", err.Error()) + return + } + } else { + if configFile != "" { + if !filepath.IsAbs(configFile) { + currentDir, _ := os.Getwd() + configFile = filepath.Join(currentDir, configFile) + } + } else { + configFile = filepath.Join(C.Path.HomeDir(), C.Path.Config()) + } + C.SetConfig(configFile) + + if err := config.Init(C.Path.HomeDir()); err != nil { + log.Fatalln("Initial configuration directory error: %s", err.Error()) + } } if testConfig { - if _, err := executor.Parse(); err != nil { - log.Errorln(err.Error()) - fmt.Printf("configuration file %s test failed\n", C.Path.Config()) - os.Exit(1) + if len(configBytes) != 0 { + if _, err := executor.ParseWithBytes(configBytes); err != nil { + log.Errorln(err.Error()) + fmt.Println("configuration test failed") + os.Exit(1) + } + } else { + if _, err := executor.Parse(); err != nil { + log.Errorln(err.Error()) + fmt.Printf("configuration file %s test failed\n", C.Path.Config()) + os.Exit(1) + } } fmt.Printf("configuration file %s test is successful\n", C.Path.Config()) return @@ -115,7 +136,7 @@ func main() { options = append(options, hub.WithSecret(secret)) } - if err := hub.Parse(options...); err != nil { + if err := hub.Parse(configBytes, options...); err != nil { log.Fatalln("Parse config error: %s", err.Error()) } @@ -134,11 +155,19 @@ func main() { case <-termSign: return case <-hupSign: - if cfg, err := executor.ParseWithPath(C.Path.Config()); err == nil { + var cfg *config.Config + var err error + if configString != "" { + cfg, err = executor.ParseWithBytes(configBytes) + } else { + cfg, err = executor.ParseWithPath(C.Path.Config()) + } + if err == nil { hub.ApplyConfig(cfg) } else { log.Errorln("Parse config error: %s", err.Error()) } + } } }