Files
clash-web/cmd/clashweb/main.go
T

60 lines
1.8 KiB
Go

package main
import (
"context"
"flag"
"log"
"net"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"clashweb/internal/app"
"clashweb/web"
)
func env(key, fallback string) string {
if value := os.Getenv(key); value != "" {
return value
}
return fallback
}
func main() {
listen := flag.String("listen", env("CLASHWEB_LISTEN", "127.0.0.1:8080"), "Web 管理监听地址")
data := flag.String("data", env("CLASHWEB_DATA_DIR", "data"), "SQLite 数据目录")
coreDir := flag.String("core-dir", os.Getenv("CLASHWEB_CORE_DIR"), "Mihomo 工作目录")
coreBin := flag.String("mihomo", os.Getenv("CLASHWEB_MIHOMO_BIN"), "Mihomo 可执行文件")
initOnly := flag.Bool("init", false, "校验并生成初始配置,然后退出")
flag.Parse()
a, err := app.New(app.Options{DataDir: *data, CoreDir: *coreDir, CoreBinary: *coreBin, Helper: os.Getenv("CLASHWEB_CONTROL_HELPER"), SecureCookie: os.Getenv("CLASHWEB_SECURE_COOKIE") == "true", Web: web.Handler()})
if err != nil {
log.Fatal(err)
}
defer a.Close()
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
if *initOnly {
if err := a.Initialize(ctx); err != nil {
log.Fatal(err)
}
log.Print("初始配置生成完成")
return
}
go a.Run(ctx)
server := &http.Server{Addr: *listen, Handler: a.Handler(), ReadHeaderTimeout: 10 * time.Second, IdleTimeout: 90 * time.Second, MaxHeaderBytes: 1 << 20, BaseContext: func(net.Listener) context.Context { return ctx }}
go func() {
<-ctx.Done()
shutdown, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
_ = server.Shutdown(shutdown)
}()
abs, _ := filepath.Abs(*data)
log.Printf("Clash Web: http://%s (数据: %s)", *listen, abs)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
}
}