feat: ent ORM, admin UI, client auth, Fyne GUI, Windows/MSI packaging

This commit is contained in:
kannn
2026-05-29 08:58:22 +00:00
Unverified
parent 8563a5fc74
commit a0a42a4966
81 changed files with 17144 additions and 89 deletions
+80
View File
@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
@@ -146,6 +147,9 @@ type Service struct {
// string if no configuration file was used.
configFilePath string
// configURL is the URL to fetch configuration from on startup and periodically.
configURL string
// service context
ctx context.Context
// call cancel to stop service
@@ -199,6 +203,7 @@ func NewService(options ServiceOptions) (*Service, error) {
common: options.Common,
reloadCommon: options.Common,
configFilePath: options.ConfigFilePath,
configURL: options.Common.ConfigURL,
unsafeFeatures: options.UnsafeFeatures,
proxyCfgs: proxyCfgs,
visitorCfgs: visitorCfgs,
@@ -265,6 +270,10 @@ func (svr *Service) Run(ctx context.Context) error {
go svr.keepControllerWorking()
if svr.configURL != "" {
go svr.pollConfigURL()
}
<-svr.ctx.Done()
svr.stop()
return nil
@@ -513,3 +522,74 @@ func (svr *Service) reloadConfigFromSourcesLocked() error {
}
return nil
}
func (svr *Service) pollConfigURL() {
url := svr.configURL
if url == "" {
return
}
log.Infof("starting config URL poller: %s", url)
lastBody := ""
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-svr.ctx.Done():
return
case <-ticker.C:
}
resp, err := http.Get(url)
if err != nil {
log.Warnf("failed to fetch config from %s: %v", url, err)
continue
}
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
log.Warnf("failed to read config from %s: %v", url, err)
continue
}
bodyStr := string(body)
if bodyStr == lastBody {
continue
}
log.Infof("config changed, reloading from %s", url)
allCfg := v1.ClientConfig{}
if err := config.LoadConfigure(body, &allCfg, false, "toml"); err != nil {
log.Warnf("failed to parse config from %s: %v", url, err)
continue
}
proxyCfgs := make([]v1.ProxyConfigurer, 0)
for _, c := range allCfg.Proxies {
proxyCfgs = append(proxyCfgs, c.ProxyConfigurer)
}
visitorCfgs := make([]v1.VisitorConfigurer, 0)
for _, c := range allCfg.Visitors {
visitorCfgs = append(visitorCfgs, c.VisitorConfigurer)
}
// Update common config for new proxies
if allCfg.ClientCommonConfig.Log.To != "" {
svr.cfgMu.Lock()
svr.reloadCommon = &allCfg.ClientCommonConfig
svr.cfgMu.Unlock()
}
if err := svr.UpdateConfigSource(&allCfg.ClientCommonConfig, proxyCfgs, visitorCfgs); err != nil {
log.Warnf("failed to apply config from %s: %v", url, err)
continue
}
lastBody = bodyStr
log.Infof("config reloaded successfully from %s", url)
}
}