feat(proxy): add proxy management endpoint and proxy creation API
- Implement new endpoint for creating frpc proxy configurations - Add DBQueryFrpcInstanceByID function to fetch instances by ID - Move proxy generation logic to separate function in frpcProxyAct.go - Update API documentation with new proxy creation endpoint
This commit is contained in:
+137
@@ -0,0 +1,137 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"super-frpc/postLog"
|
||||
)
|
||||
|
||||
type CreateProxyRequest struct {
|
||||
InstanceID string `json:"instanceID"`
|
||||
ProxyInfo FrpcProxyInfo `json:"proxyInfo"`
|
||||
}
|
||||
|
||||
func CreateProxyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method")
|
||||
postLog.Debug(fmt.Sprintf("[CreateProxyHandler] Invalid request method: %s", r.Method))
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to read request body: %v", err))
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
var reqMap map[string]interface{}
|
||||
if err := json.Unmarshal(body, &reqMap); err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to unmarshal request body: %v", err))
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Invalid request format")
|
||||
return
|
||||
}
|
||||
|
||||
instanceID := getStringFromMap(reqMap, "instanceID")
|
||||
if instanceID == "" {
|
||||
postLog.Error("[CreateProxyHandler] instanceID is required")
|
||||
SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
|
||||
return
|
||||
}
|
||||
|
||||
proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{})
|
||||
if !ok {
|
||||
postLog.Error("[CreateProxyHandler] Invalid proxyInfo format")
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format")
|
||||
return
|
||||
}
|
||||
|
||||
proxyInfo := FrpcProxyInfo{
|
||||
Name: getStringFromMap(proxyInfoMap, "name"),
|
||||
Type: getStringFromMap(proxyInfoMap, "type"),
|
||||
LocalIP: getStringFromMap(proxyInfoMap, "localIP"),
|
||||
LocalPort: getStringFromMap(proxyInfoMap, "localPort"),
|
||||
RemotePort: getStringFromMap(proxyInfoMap, "remotePort"),
|
||||
}
|
||||
|
||||
if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" ||
|
||||
proxyInfo.LocalPort == "" || proxyInfo.RemotePort == "" {
|
||||
postLog.Error("[CreateProxyHandler] Missing required fields in proxyInfo")
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in proxyInfo")
|
||||
return
|
||||
}
|
||||
|
||||
userID, _, err := ValidateRequestWithHeader(w, r)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to validate request header: %v", err))
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Invalid request header")
|
||||
return
|
||||
}
|
||||
|
||||
userType, err := GetUserType(userID)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to get user type: %v", err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user type")
|
||||
return
|
||||
} else if userType != "admin" && userType != "superuser" {
|
||||
SendErrorResponse(w, http.StatusForbidden, "Permission Denied")
|
||||
return
|
||||
}
|
||||
|
||||
var instance FrpcInstance
|
||||
instanceIDInt, _ := strconv.Atoi(instanceID)
|
||||
instance, err = DBQueryFrpcInstanceByID(instanceIDInt)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to query instance: %v", err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance")
|
||||
return
|
||||
}
|
||||
|
||||
if instance.UserID != userID {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Instance not found for user %d", userID))
|
||||
SendErrorResponse(w, http.StatusNotFound, "Instance not found")
|
||||
return
|
||||
}
|
||||
|
||||
configContent, err := os.ReadFile(instance.ConfigPath)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file")
|
||||
return
|
||||
}
|
||||
|
||||
proxyConfig := addFrpcProxy(proxyInfo)
|
||||
updatedContent := string(configContent) + proxyConfig
|
||||
|
||||
if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil {
|
||||
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to write config file %s: %v", instance.ConfigPath, err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file")
|
||||
return
|
||||
}
|
||||
|
||||
SendSuccessResponse(w, "Proxy created successfully", map[string]interface{}{
|
||||
"instanceName": instance.Name,
|
||||
"instanceID": instance.ID,
|
||||
"configPath": instance.ConfigPath,
|
||||
"proxyName": proxyInfo.Name,
|
||||
})
|
||||
postLog.Info(fmt.Sprintf("[CreateProxyHandler] Proxy %s created successfully for instance %s", proxyInfo.Name, instance.Name))
|
||||
}
|
||||
|
||||
func addFrpcProxy(info FrpcProxyInfo) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("\n[[proxies]]\n")
|
||||
sb.WriteString(fmt.Sprintf("name = %s\n", info.Name))
|
||||
sb.WriteString(fmt.Sprintf("type = %s\n", info.Type))
|
||||
sb.WriteString(fmt.Sprintf("local_ip = %s\n", info.LocalIP))
|
||||
sb.WriteString(fmt.Sprintf("local_port = %s\n", info.LocalPort))
|
||||
sb.WriteString(fmt.Sprintf("remote_port = %s\n", info.RemotePort))
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
Reference in New Issue
Block a user