feat(instanceMgr): add getInfo endpoint to retrieve instance details
Implement new GET endpoint `/frpcAct/instanceMgr/getInfo` to fetch frpc instance information Add documentation for the new API endpoint in docs/api.md The handler returns different information based on user permission level
This commit is contained in:
+85
@@ -1165,6 +1165,91 @@ X-Timestamp: 1704067200000
|
||||
|
||||
---
|
||||
|
||||
## Get frpc Instance Information
|
||||
|
||||
**Endpoint:** `/frpcAct/instanceMgr/getInfo`
|
||||
**Method:** GET
|
||||
**Auth Required:** Yes (token)
|
||||
**Permission Level:** Visitor
|
||||
|
||||
Retrieve information about a specific frpc instance. Returns different information based on user permission level.
|
||||
|
||||
**Request Headers:**
|
||||
```
|
||||
X-Token: your_token
|
||||
X-Timestamp: 1704067200000
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
```
|
||||
instanceID=1
|
||||
```
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|----------|-------------|
|
||||
| X-Token | string | Yes | Authentication token |
|
||||
| X-Timestamp | int64 | Yes | Client timestamp in milliseconds |
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| instanceID | string | Yes | ID of the instance to get information for |
|
||||
|
||||
**Response (Admin/Superuser):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Instance info retrieved successfully",
|
||||
"data": {
|
||||
"name": "my_frpc",
|
||||
"serviceName": "superfrpc_admin_my_frpc",
|
||||
"createdAt": "2024-01-01T00:00:00Z",
|
||||
"createdBy": "admin",
|
||||
"isRunning": true,
|
||||
"serverAddr": "127.0.0.1",
|
||||
"serverPort": "7000",
|
||||
"auth_method": "token",
|
||||
"bootAtStart": true,
|
||||
"runUser": "root",
|
||||
"configPath": "./configs/superfrpc_admin_my_frpc.toml"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response (Visitor):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Instance info retrieved successfully",
|
||||
"data": {
|
||||
"name": "my_frpc",
|
||||
"serviceName": "superfrpc_admin_my_frpc",
|
||||
"createdAt": "2024-01-01T00:00:00Z",
|
||||
"createdBy": "admin",
|
||||
"isRunning": true,
|
||||
"auth_method": "token",
|
||||
"bootAtStart": true,
|
||||
"runUser": "root",
|
||||
"configPath": "./configs/superfrpc_admin_my_frpc.toml"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| name | string | Name of the frpc instance |
|
||||
| serviceName | string | Service name |
|
||||
| createdAt | string | Instance creation time (ISO 8601 format) |
|
||||
| createdBy | string | Username of the user who created this instance |
|
||||
| isRunning | bool | Instance running status: true (running) or false (stopped) |
|
||||
| serverAddr | string | frps server address (only returned for admin/superuser) |
|
||||
| serverPort | string | frps server port (only returned for admin/superuser) |
|
||||
| auth_method | string | Authentication method |
|
||||
| bootAtStart | bool | Whether the instance starts automatically on system boot |
|
||||
| runUser | string | User that the instance runs as |
|
||||
| configPath | string | Path to the instance's configuration file |
|
||||
|
||||
---
|
||||
|
||||
## Real-time Log Streaming (WebSocket)
|
||||
|
||||
**Endpoint:** `/system/getLogs`
|
||||
|
||||
@@ -972,3 +972,99 @@ func GetInstanceStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
SendSuccessResponse(w, "Instance status retrieved successfully", responseData)
|
||||
postLog.Info(fmt.Sprintf("[GetInstanceStatusHandler] Retrieved status for instance %d (name: %s), isRunning: %v", instanceID, instance.Name, isRunning))
|
||||
}
|
||||
|
||||
func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method")
|
||||
postLog.Debug(fmt.Sprintf("[GetInstanceInfoHandler] Invalid request method: %s", r.Method))
|
||||
return
|
||||
}
|
||||
|
||||
queryParams := r.URL.Query()
|
||||
instanceIDStr := queryParams.Get("instanceID")
|
||||
if instanceIDStr == "" {
|
||||
SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
|
||||
return
|
||||
}
|
||||
|
||||
instanceID, err := strconv.Atoi(instanceIDStr)
|
||||
if err != nil {
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
|
||||
return
|
||||
}
|
||||
|
||||
userID, _, err := ValidateRequestWithHeader(w, r)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to validate request header: %v", err))
|
||||
SendErrorResponse(w, http.StatusBadRequest, "Invalid request header")
|
||||
return
|
||||
}
|
||||
|
||||
instance, err := DBQueryFrpcInstanceByID(instanceID)
|
||||
if err == sql.ErrNoRows {
|
||||
SendErrorResponse(w, http.StatusNotFound, "Instance not found")
|
||||
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] User %d tried to get info of a not existed instance: %d", userID, instanceID))
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to query instance: %v", err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance")
|
||||
return
|
||||
}
|
||||
|
||||
if instance.UserID != userID {
|
||||
SendErrorResponse(w, http.StatusForbidden, "Instance not found")
|
||||
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] User %d tried to get info of instance %d that does not belong to them", userID, instanceID))
|
||||
return
|
||||
}
|
||||
|
||||
userType, err := GetUserType(userID)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to get user type: %v", err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user type")
|
||||
return
|
||||
}
|
||||
|
||||
serviceName, err := GetServiceNameByInstanceID(instanceID)
|
||||
if err != nil {
|
||||
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to get service name: %v", err))
|
||||
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name")
|
||||
return
|
||||
}
|
||||
|
||||
isRunning := IsInstanceRunning(instanceID)
|
||||
|
||||
responseData := map[string]interface{}{
|
||||
"name": instance.Name,
|
||||
"serviceName": serviceName,
|
||||
"createdAt": instance.CreatedAt,
|
||||
"createdBy": instance.CreatedBy,
|
||||
"isRunning": isRunning,
|
||||
"auth_method": "",
|
||||
"bootAtStart": instance.BootAtStart,
|
||||
"runUser": instance.RunUser,
|
||||
"configPath": instance.ConfigPath,
|
||||
}
|
||||
|
||||
configContent, err := os.ReadFile(instance.ConfigPath)
|
||||
if err == nil {
|
||||
config, err := decodeFrpcConfig(string(configContent))
|
||||
if err == nil {
|
||||
if authMethod, ok := config.Global["auth.method"]; ok {
|
||||
responseData["auth_method"] = authMethod
|
||||
}
|
||||
|
||||
if userType == "admin" || userType == "superuser" {
|
||||
if serverAddr, ok := config.Global["serverAddr"]; ok {
|
||||
responseData["serverAddr"] = serverAddr
|
||||
}
|
||||
if serverPort, ok := config.Global["serverPort"]; ok {
|
||||
responseData["serverPort"] = serverPort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendSuccessResponse(w, "Instance info retrieved successfully", responseData)
|
||||
postLog.Info(fmt.Sprintf("[GetInstanceInfoHandler] Retrieved info for instance %d (name: %s), userType: %s", instanceID, instance.Name, userType))
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ func setupRoutes() {
|
||||
http.HandleFunc("/frpcAct/instanceMgr/stop", StopInstanceHandler)
|
||||
http.HandleFunc("/frpcAct/instanceMgr/restart", RestartInstanceHandler)
|
||||
http.HandleFunc("/frpcAct/instanceMgr/status", GetInstanceStatusHandler)
|
||||
http.HandleFunc("/frpcAct/instanceMgr/getInfo", GetInstanceInfoHandler)
|
||||
http.HandleFunc("/frpcAct/proxyMgr/create", CreateProxyHandler)
|
||||
http.HandleFunc("/frpcAct/proxyMgr/delete", DeleteProxyHandler)
|
||||
http.HandleFunc("/frpcAct/proxyMgr/list", ListProxiesHandler)
|
||||
|
||||
Reference in New Issue
Block a user