feat(handlers): add duplicate login check and improve request handling
refactor: move postLog package to root directory and enhance logging fix(frpc): improve request parsing and type handling for instance creation chore: update config paths and enable debug mode
This commit is contained in:
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"listenAddr": "0.0.0.0",
|
"listenAddr": "0.0.0.0",
|
||||||
"listenPort": "8080",
|
"listenPort": "8080",
|
||||||
"frpcPath": "/usr/bin/frpc",
|
"frpcPath": "Y:\\Sources\\Projects\\Super-frpc\\frp_0.67.0_windows_amd64\\frpc.exe",
|
||||||
"instancePath": "./configs",
|
"instancePath": "./configs",
|
||||||
"debug": false
|
"debug": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[common]
|
||||||
|
server_addr = 127.0.0.1
|
||||||
|
server_port = 7000
|
||||||
|
auth_method = token
|
||||||
|
=
|
||||||
BIN
Binary file not shown.
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -102,13 +103,79 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
var req CreateInstanceRequest
|
// 先解析为map,处理类型不匹配的情况
|
||||||
if err := json.Unmarshal(body, &req); err != nil {
|
var reqMap map[string]interface{}
|
||||||
|
if err := json.Unmarshal(body, &reqMap); err != nil {
|
||||||
SendErrorResponse(w, http.StatusBadRequest, "invalid request format")
|
SendErrorResponse(w, http.StatusBadRequest, "invalid request format")
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
SendErrorResponse(w, http.StatusUnauthorized, err.Error())
|
SendErrorResponse(w, http.StatusUnauthorized, err.Error())
|
||||||
return
|
return
|
||||||
@@ -745,3 +812,10 @@ func GetUserInstances(userID int) ([]FrpcInstance, error) {
|
|||||||
|
|
||||||
return instances, nil
|
return instances, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getStringFromMap(m map[string]interface{}, key string) string {
|
||||||
|
if v, ok := m[key].(string); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
+7
-1
@@ -7,7 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"super-frpc/modules"
|
"super-frpc/postLog"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -150,6 +150,12 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
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)
|
token, err := GenerateToken(user.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
SendErrorResponse(w, http.StatusInternalServerError, "failed to generate token")
|
SendErrorResponse(w, http.StatusInternalServerError, "failed to generate token")
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"super-frpc/modules"
|
"super-frpc/postLog"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -23,31 +23,31 @@ func main() {
|
|||||||
"configDir": "./configs"
|
"configDir": "./configs"
|
||||||
}`
|
}`
|
||||||
if err := os.WriteFile(*configPath, []byte(defaultConfig), 0644); err != nil {
|
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)
|
config, err := LoadConfig(*configPath)
|
||||||
if err != nil {
|
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
|
// Initialize logger with debug mode
|
||||||
postLog.SetDebugMode(config.Debug)
|
postLog.SetDebugMode(config.Debug)
|
||||||
|
|
||||||
if err := InitDatabase(*dbPath); err != nil {
|
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 {
|
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()
|
_, err = GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
postLog.Fatal(fmt.Sprintf("failed to get config: %v", err))
|
postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
setupRoutes()
|
setupRoutes()
|
||||||
@@ -61,9 +61,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
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 {
|
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)
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-quit
|
<-quit
|
||||||
|
|
||||||
postLog.Info("shutting down server...")
|
postLog.Info("Shutting down server...")
|
||||||
|
|
||||||
if err := server.Close(); err != nil {
|
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 {
|
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 {
|
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")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user