Files
backend/main.go
NanamiAdmin ddf91299e7 refactor: reorganize codebase into modular packages
feat(global): add global package for shared variables and types
refactor(handlers): move handlers to dedicated package and update imports
refactor(session): extract session management to separate package
refactor(config): move config handling to dedicated package
refactor(router): update route handlers to use new package structure
refactor(main): simplify main.go by moving logic to packages
2026-04-22 12:57:04 +08:00

148 lines
4.1 KiB
Go

package main
import (
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"super-frpc/config"
"super-frpc/database"
"super-frpc/frpLogger"
"super-frpc/global"
"super-frpc/handlers"
"super-frpc/postLog"
"super-frpc/session"
"super-frpc/service"
"super-frpc/watchdog"
"syscall"
"time"
)
func main() {
postLog.Info(fmt.Sprintf("%s %s (Build %d.%s) by %s", global.Software.Name, global.Software.Version, global.Software.BuildVer, global.Software.BuildType, global.Software.Developer))
configPath := flag.String("config", "./config.json", "path to config file")
dbPath_data := flag.String("db", "./database.db", "path to database file")
dbPath_log := flag.String("log", "./logs.db", "path to logs database file")
flag.Parse()
if _, err := os.Stat(*configPath); os.IsNotExist(err) {
defaultConfig := `{
"listenAddr": "0.0.0.0",
"listenPort": "8080",
"configDir": "./configs"
}`
if err := os.WriteFile(*configPath, []byte(defaultConfig), 0644); err != nil {
postLog.Warning(fmt.Sprintf("Failed to create default config file: %v", err))
}
postLog.Info(fmt.Sprintf("Created default config file at %s", *configPath))
}
cfg, err := config.LoadConfig(*configPath, service.GetInitSystem)
if err != nil {
postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err))
}
postLog.SetDebugMode(cfg.Debug)
global.Is.Debug = cfg.Debug
if err := postLog.InitLogsDatabase(*dbPath_log); err != nil {
postLog.Fatal(fmt.Sprintf("Failed to initialize logs database: %v", err))
}
postLog.Info("Logs database initialized successfully")
if err := database.InitDatabase(*dbPath_data, *dbPath_log); err != nil {
postLog.Fatal(fmt.Sprintf("Failed to initialize database: %v", err))
}
postLog.Info("Database initialized successfully")
if err := database.InitFrpcDatabase(*dbPath_data); err != nil {
postLog.Fatal(fmt.Sprintf("Failed to initialize frpc database: %v", err))
}
frpLogger.SetDatabase(global.ConfigDB, global.FrpcDB)
frpLogger.SetDebugMode(cfg.Debug)
_, err = config.GetConfig()
if err != nil {
postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err))
}
postLog.InitLogBroadcaster()
setupRoutes()
err = watchdog.Init()
if err != nil {
postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err))
} else {
if !watchdog.Connect("127.0.0.1", cfg.Watchdog.Port) {
postLog.Error(fmt.Sprintf("Failed to connect to Watchdog at %s:%d", "127.0.0.1", cfg.Watchdog.Port))
} else {
postLog.Info(fmt.Sprintf("Connected to Watchdog at %s:%d", "127.0.0.1", cfg.Watchdog.Port))
global.Is.WatchdogConnected = true
}
}
addr := fmt.Sprintf("%s:%s", cfg.ListenAddr, cfg.ListenPort)
server := &http.Server{
Addr: addr,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
go func() {
postLog.Info(fmt.Sprintf("Server starting on %s", addr))
global.Is.Online = true
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
postLog.Fatal(fmt.Sprintf("Failed to start server: %v", err))
}
}()
go func() {
ticker := time.NewTicker(1 * time.Hour)
defer ticker.Stop()
for range ticker.C {
session.CleanupExpiredTokens()
session.CleanupExpiredSessions()
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
postLog.Info("Shutting down server...")
if err := server.Close(); err != nil {
postLog.Error(fmt.Sprintf("Server closed with error: %v", err))
}
if err := database.CloseDatabase(); err != nil {
postLog.Error(fmt.Sprintf("Error closing database: %v", err))
}
watchdog.Close()
postLog.Info("Server stopped")
}
func GetStatusHandler(w http.ResponseWriter, r *http.Request) {
statusInfo := map[string]string{
"ServerStatus": "Offline",
"WatchdogStatus": "Offline",
}
if global.Is.Online {
statusInfo["ServerStatus"] = "Online"
}
if global.Is.WatchdogConnected {
statusInfo["WatchdogStatus"] = "Online"
}
handlers.SendSuccessResponse(w, "getStatus", statusInfo)
}
func GetSoftwareInfoHandler(w http.ResponseWriter, r *http.Request) {
handlers.SendSuccessResponse(w, "getSoftwareInfo", global.Software)
}