diff --git a/configs/superfrpc_test_test123.toml b/configs/superfrpc_test_test123.toml new file mode 100644 index 0000000..5a5eeaa --- /dev/null +++ b/configs/superfrpc_test_test123.toml @@ -0,0 +1,5 @@ +[common] +server_addr = 127.0.0.1 +server_port = 7000 +auth_method = token + = diff --git a/database.db b/database.db index 1e1667d..1c8410e 100644 Binary files a/database.db and b/database.db differ diff --git a/frpc.go b/frpc.go index 081a0de..ad89efa 100644 --- a/frpc.go +++ b/frpc.go @@ -10,18 +10,19 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "time" ) type InstanceInfo struct { - Name string `json:"name"` - ServerAddr string `json:"serverAddr"` - ServerPort string `json:"serverPort"` - AuthMethod string `json:"auth_method"` + Name string `json:"name"` + ServerAddr string `json:"serverAddr"` + ServerPort string `json:"serverPort"` + AuthMethod string `json:"auth_method"` // BootAtStart bool `json:"bootAtStart"` - RunUser string `json:"runUser"` - Additional map[string]interface{} `json:"additionalProperties"` + RunUser string `json:"runUser"` + Additional map[string]interface{} `json:"additionalProperties"` } type CreateInstanceRequest struct { @@ -102,13 +103,79 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { } defer r.Body.Close() - var req CreateInstanceRequest - if err := json.Unmarshal(body, &req); err != nil { + // 先解析为map,处理类型不匹配的情况 + var reqMap map[string]interface{} + if err := json.Unmarshal(body, &reqMap); err != nil { SendErrorResponse(w, http.StatusBadRequest, "invalid request format") return } - userID, _, err := ValidateRequestWithBody(w, r, body) + // 处理timeStamp字段 + timeStamp := int64(0) + if ts, ok := reqMap["timeStamp"]; ok { + switch v := ts.(type) { + case float64: + timeStamp = int64(v) + case string: + if v != "" { + if parsed, err := strconv.ParseInt(v, 10, 64); err == nil { + timeStamp = parsed + } + } + } + } + + // 处理bootAtStart字段 + bootAtStart := false + if bas, ok := reqMap["bootAtStart"]; ok { + switch v := bas.(type) { + case bool: + bootAtStart = v + case string: + if v == "true" { + bootAtStart = true + } + } + } + + // 处理instanceInfo字段 + instanceInfoMap, ok := reqMap["instanceInfo"].(map[string]interface{}) + if !ok { + SendErrorResponse(w, http.StatusBadRequest, "invalid instanceInfo format") + return + } + + instanceInfo := InstanceInfo{ + Name: getStringFromMap(instanceInfoMap, "name"), + ServerAddr: getStringFromMap(instanceInfoMap, "serverAddr"), + ServerPort: getStringFromMap(instanceInfoMap, "serverPort"), + AuthMethod: getStringFromMap(instanceInfoMap, "auth_method"), + RunUser: getStringFromMap(reqMap, "runUser"), + } + + // 处理additionalProperties字段 + if additional, ok := reqMap["additionalProperties"].(map[string]interface{}); ok { + instanceInfo.Additional = additional + } + + // 构建请求结构体 + req := CreateInstanceRequest{ + Token: getStringFromMap(reqMap, "token"), + TimeStamp: timeStamp, + InstanceInfo: instanceInfo, + BootAtStart: bootAtStart, + RunUser: instanceInfo.RunUser, + Additional: instanceInfo.Additional, + } + + // 重新序列化为JSON,用于ValidateRequestWithBody + reqBody, err := json.Marshal(req) + if err != nil { + SendErrorResponse(w, http.StatusBadRequest, "invalid request format") + return + } + + userID, _, err := ValidateRequestWithBody(w, r, reqBody) if err != nil { SendErrorResponse(w, http.StatusUnauthorized, err.Error()) return @@ -745,3 +812,10 @@ func GetUserInstances(userID int) ([]FrpcInstance, error) { return instances, nil } + +func getStringFromMap(m map[string]interface{}, key string) string { + if v, ok := m[key].(string); ok { + return v + } + return "" +} diff --git a/handlers.go b/handlers.go index ea10ddd..6f65c58 100644 --- a/handlers.go +++ b/handlers.go @@ -7,7 +7,7 @@ import ( "io" "net/http" "strconv" - "super-frpc/modules" + "super-frpc/postLog" "time" ) @@ -150,6 +150,12 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { return } + existingTokenInfo, err := GetTokenInfo(user.UserID) + if err == nil && existingTokenInfo != nil { + SendErrorResponse(w, http.StatusConflict, "user is already logged in") + return + } + token, err := GenerateToken(user.UserID) if err != nil { SendErrorResponse(w, http.StatusInternalServerError, "failed to generate token") diff --git a/main.go b/main.go index 6c19271..a9d43ad 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ import ( "net/http" "os" "os/signal" - "super-frpc/modules" + "super-frpc/postLog" "syscall" "time" ) @@ -23,31 +23,31 @@ func main() { "configDir": "./configs" }` if err := os.WriteFile(*configPath, []byte(defaultConfig), 0644); err != nil { - postLog.Fatal(fmt.Sprintf("failed to create default config file: %v", err)) + postLog.Fatal(fmt.Sprintf("Failed to create default config file: %v", err)) } - postLog.Info(fmt.Sprintf("created default config file at %s", *configPath)) + postLog.Info(fmt.Sprintf("Created default config file at %s", *configPath)) } config, err := LoadConfig(*configPath) if err != nil { - postLog.Fatal(fmt.Sprintf("failed to load config: %v", err)) + postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err)) } // Initialize logger with debug mode postLog.SetDebugMode(config.Debug) if err := InitDatabase(*dbPath); err != nil { - postLog.Fatal(fmt.Sprintf("failed to initialize database: %v", err)) + postLog.Fatal(fmt.Sprintf("Failed to initialize database: %v", err)) } - postLog.Info("database initialized successfully") + postLog.Info("Database initialized successfully") if err := InitFrpcDatabase(*dbPath); err != nil { - postLog.Warning(fmt.Sprintf("failed to initialize frpc database: %v", err)) + postLog.Warning(fmt.Sprintf("Failed to initialize frpc database: %v", err)) } _, err = GetConfig() if err != nil { - postLog.Fatal(fmt.Sprintf("failed to get config: %v", err)) + postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err)) } setupRoutes() @@ -61,9 +61,9 @@ func main() { } go func() { - postLog.Info(fmt.Sprintf("server starting on %s", addr)) + postLog.Info(fmt.Sprintf("Server starting on %s", addr)) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - postLog.Fatal(fmt.Sprintf("failed to start server: %v", err)) + postLog.Fatal(fmt.Sprintf("Failed to start server: %v", err)) } }() @@ -71,19 +71,19 @@ func main() { signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit - postLog.Info("shutting down server...") + postLog.Info("Shutting down server...") if err := server.Close(); err != nil { - postLog.Error(fmt.Sprintf("server closed with error: %v", err)) + postLog.Error(fmt.Sprintf("Server closed with error: %v", err)) } if err := CloseDatabase(); err != nil { - postLog.Error(fmt.Sprintf("error closing database: %v", err)) + postLog.Error(fmt.Sprintf("Error closing database: %v", err)) } if err := CloseFrpcDatabase(); err != nil { - postLog.Error(fmt.Sprintf("error closing frpc database: %v", err)) + postLog.Error(fmt.Sprintf("Error closing frpc database: %v", err)) } - postLog.Info("server stopped") + postLog.Info("Server stopped") } diff --git a/modules/postLog.go b/postLog/postLog.go similarity index 100% rename from modules/postLog.go rename to postLog/postLog.go