--- a/cmd/sing-box/cmd_run.go +++ b/cmd/sing-box/cmd_run.go @@ -3,6 +3,7 @@ import ( "context" "io" + "net/http" // OMV "os" "os/signal" "path/filepath" @@ -49,8 +50,36 @@ configContent []byte err error ) + // OMV start: fetch subscription from env + subscriptionLink := os.Getenv("SING_SUBSCRIPTION_LINK") + subscriptionCache := os.Getenv("SING_SUBSCRIPTION_CACHE") + // OMV end if path == "stdin" { configContent, err = io.ReadAll(os.Stdin) + // OMV start: fetch subscription from env + } else if path == "env" && subscriptionLink != "" { + configContentResponse, err := http.Get(subscriptionLink) + if err != nil { + log.Warn("Cannot fetch subscription: ", err) + } + if err != nil || configContentResponse.StatusCode != 200 { + if subscriptionCache != "" { + log.Info("using previous subscription cache") + configContent, err = os.ReadFile(subscriptionCache) + } else { + return nil, E.Cause(err, "failed to GET subscription link") + } + } else { + defer configContentResponse.Body.Close() + configContent, err = io.ReadAll(configContentResponse.Body) + if err == nil && subscriptionCache != "" { + _err := os.WriteFile(subscriptionCache, configContent, 0600) + if _err != nil { + log.Error(E.Cause(_err, "failed to cache subscription file")) + } + } + } + // OMV end } else { configContent, err = os.ReadFile(path) }