Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。 Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/wormhole/wormhole/internal/api"
|
||||
"github.com/wormhole/wormhole/internal/auth"
|
||||
"github.com/wormhole/wormhole/internal/bridge"
|
||||
"github.com/wormhole/wormhole/internal/cache"
|
||||
"github.com/wormhole/wormhole/internal/config"
|
||||
"github.com/wormhole/wormhole/internal/metrics"
|
||||
"github.com/wormhole/wormhole/internal/proxy"
|
||||
"github.com/wormhole/wormhole/internal/security"
|
||||
"github.com/wormhole/wormhole/internal/store"
|
||||
webdist "github.com/wormhole/wormhole/web"
|
||||
)
|
||||
|
||||
func Run(args []string) {
|
||||
fs := flag.NewFlagSet("server", flag.ExitOnError)
|
||||
fs.Parse(args)
|
||||
|
||||
st, err := store.Open(config.DefaultDBPath)
|
||||
if err != nil {
|
||||
log.Fatalf("open store: %v", err)
|
||||
}
|
||||
|
||||
cfg, err := st.LoadConfig()
|
||||
if err != nil {
|
||||
log.Fatalf("load settings: %v", err)
|
||||
}
|
||||
log.Printf("[server] settings loaded (%s)", cfg.Summary())
|
||||
|
||||
c := cache.NewManager()
|
||||
if err := c.ReloadAll(st); err != nil {
|
||||
log.Fatalf("reload cache: %v", err)
|
||||
}
|
||||
|
||||
authSvc := auth.NewService(&cfg.Auth)
|
||||
resAuth := auth.NewResourceAuth(c, st, &cfg.Auth)
|
||||
sec := security.NewService(c, st)
|
||||
b := bridge.New(c, st)
|
||||
mc := metrics.NewCollector(st, c, b)
|
||||
pm := proxy.NewManager(c, st, b, sec, resAuth, mc)
|
||||
|
||||
if err := b.Start(cfg.Server.BridgeAddr, cfg.Server.TLSCertFile, cfg.Server.TLSKeyFile); err != nil {
|
||||
log.Fatalf("bridge start: %v", err)
|
||||
}
|
||||
mc.Start(cfg.Metrics.FlushInterval)
|
||||
if err := pm.StartAll(); err != nil {
|
||||
log.Printf("start tunnels: %v", err)
|
||||
}
|
||||
if err := pm.StartHTTPServer(cfg.Server.HTTPProxyPort, cfg.Server.HTTPSProxyPort, cfg.Server.TLSCertFile, cfg.Server.TLSKeyFile); err != nil {
|
||||
log.Printf("start http proxy: %v", err)
|
||||
}
|
||||
|
||||
apiServer := api.NewServer(cfg, st, c, authSvc, resAuth, sec, b, pm, mc)
|
||||
router := apiServer.Router()
|
||||
router.NoRoute(serveSPA())
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: cfg.Server.HTTPAddr,
|
||||
Handler: router,
|
||||
}
|
||||
go func() {
|
||||
log.Printf("[server] http api on %s", cfg.Server.HTTPAddr)
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("http server: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sig
|
||||
log.Println("[server] shutting down...")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
mc.Stop()
|
||||
if err := pm.Shutdown(ctx); err != nil {
|
||||
log.Printf("[server] proxy shutdown: %v", err)
|
||||
}
|
||||
_ = b.Shutdown()
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
log.Printf("[server] api shutdown: %v", err)
|
||||
}
|
||||
log.Println("[server] stopped")
|
||||
}
|
||||
|
||||
func serveSPA() gin.HandlerFunc {
|
||||
distFS, err := fs.Sub(webdist.Dist, "dist")
|
||||
if err != nil {
|
||||
return func(c *gin.Context) {
|
||||
c.String(http.StatusOK, "Wormhole API running. Build web dist for UI.")
|
||||
}
|
||||
}
|
||||
fileServer := http.FileServer(http.FS(distFS))
|
||||
return func(c *gin.Context) {
|
||||
path := c.Request.URL.Path
|
||||
if path == "/" {
|
||||
path = "/index.html"
|
||||
}
|
||||
if f, err := distFS.Open(path[1:]); err == nil {
|
||||
_ = f.Close()
|
||||
fileServer.ServeHTTP(c.Writer, c.Request)
|
||||
return
|
||||
}
|
||||
c.Request.URL.Path = "/"
|
||||
fileServer.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user