Files
backend/main.go
T
NanamiAdmin 934190eebf feat: implement core functionality for super-frpc service
This commit introduces the core functionality for the super-frpc service including:
- Configuration management
- User authentication and authorization
- Database integration
- FRPC instance management
- API endpoints for user operations
- Token-based authentication system
- Password hashing and validation
2026-02-23 00:19:57 +08:00

142 lines
3.5 KiB
Go

package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
)
func main() {
configPath := flag.String("config", "./config.json", "path to config file")
dbPath := flag.String("db", "./database.db", "path to 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 {
log.Fatalf("failed to create default config file: %v", err)
}
log.Printf("created default config file at %s", *configPath)
}
_, err := LoadConfig(*configPath)
if err != nil {
log.Fatalf("failed to load config: %v", err)
}
if err := InitDatabase(*dbPath); err != nil {
log.Fatalf("failed to initialize database: %v", err)
}
log.Println("database initialized successfully")
if err := InitFrpcDatabase(*dbPath); err != nil {
log.Printf("warning: failed to initialize frpc database: %v", err)
}
config, err := GetConfig()
if err != nil {
log.Fatalf("failed to get config: %v", err)
}
setupRoutes()
addr := fmt.Sprintf("%s:%s", config.ListenAddr, config.ListenPort)
server := &http.Server{
Addr: addr,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
go func() {
log.Printf("server starting on %s", addr)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("failed to start server: %v", err)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("shutting down server...")
if err := server.Close(); err != nil {
log.Printf("server closed with error: %v", err)
}
if err := CloseDatabase(); err != nil {
log.Printf("error closing database: %v", err)
}
if err := CloseFrpcDatabase(); err != nil {
log.Printf("error closing frpc database: %v", err)
}
log.Println("server stopped")
}
func setupRoutes() {
http.HandleFunc("/register", RegisterHandler)
http.HandleFunc("/login", LoginHandler)
http.HandleFunc("/frpcAct/instanceMgr/create", CreateInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/list", ListInstancesHandler)
http.HandleFunc("/frpcAct/instanceMgr/", func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
if len(path) < len("/frpcAct/instanceMgr/") {
SendErrorResponse(w, http.StatusNotFound, "invalid path")
return
}
remainingPath := path[len("/frpcAct/instanceMgr/"):]
if r.Method == http.MethodPost {
if remainingPath == "create" {
CreateInstanceHandler(w, r)
return
}
if remainingPath == "list" {
ListInstancesHandler(w, r)
return
}
if strings.HasSuffix(remainingPath, "/delete") {
instanceName := strings.TrimSuffix(remainingPath, "/delete")
instanceName = strings.Trim(instanceName, "/")
DeleteInstanceHandler(w, r, instanceName)
return
}
if strings.Contains(remainingPath, "/modify/") {
parts := strings.SplitN(remainingPath, "/modify/", 2)
if len(parts) == 2 {
instanceName := strings.Trim(parts[0], "/")
ModifyInstanceHandler(w, r, instanceName)
return
}
}
instanceName := strings.Trim(remainingPath, "/")
if instanceName != "" {
ListInstancesHandler(w, r)
return
}
}
SendErrorResponse(w, http.StatusNotFound, "endpoint not found")
})
}