[优化] 增加 FRPS WebUI 支持,添加相关配置和数据库迁移

This commit is contained in:
ryan
2026-06-01 21:59:42 +08:00
parent d6e7e2baa2
commit fefe205158
14 changed files with 352 additions and 42 deletions
+1
View File
@@ -171,6 +171,7 @@ type NodeView struct {
RelayClientAccessAddr string `json:"relay_client_access_addr"`
RelayClientProxyURL string `json:"relay_client_proxy_url"`
RelayStatus string `json:"relay_status"`
RelayWebServerEnabled bool `json:"relay_web_server_enabled"`
}
func HeartbeatNode(node *model.Node, payload AgentNodePayload) (*HeartbeatResponse, error) {
+4
View File
@@ -31,6 +31,7 @@ type NodeInput struct {
RelayAgentAccessAddr string `json:"relay_agent_access_addr"`
RelayClientAccessAddr string `json:"relay_client_access_addr"`
RelayClientProxyURL string `json:"relay_client_proxy_url"`
RelayWebServerEnabled bool `json:"relay_web_server_enabled"`
}
type NodeAgentUpdateInput struct {
@@ -100,6 +101,7 @@ func CreateNode(input NodeInput) (*NodeView, error) {
node.RelayAgentAccessAddr = strings.TrimSpace(input.RelayAgentAccessAddr)
node.RelayClientAccessAddr = strings.TrimSpace(input.RelayClientAccessAddr)
node.RelayClientProxyURL = strings.TrimSpace(input.RelayClientProxyURL)
node.RelayWebServerEnabled = input.RelayWebServerEnabled
}
if !node.GeoManualOverride {
applyGeoInfoFromIP(node, node.IP)
@@ -137,6 +139,7 @@ func UpdateNode(id uint, input NodeInput) (*NodeView, error) {
node.RelayAgentAccessAddr = strings.TrimSpace(input.RelayAgentAccessAddr)
node.RelayClientAccessAddr = strings.TrimSpace(input.RelayClientAccessAddr)
node.RelayClientProxyURL = strings.TrimSpace(input.RelayClientProxyURL)
node.RelayWebServerEnabled = input.RelayWebServerEnabled
if input.RelayBindPort > 0 {
node.RelayBindPort = input.RelayBindPort
}
@@ -354,6 +357,7 @@ func buildNodeView(node *model.Node) *NodeView {
view.RelayClientAccessAddr = node.RelayClientAccessAddr
view.RelayClientProxyURL = node.RelayClientProxyURL
view.RelayStatus = node.RelayStatus
view.RelayWebServerEnabled = node.RelayWebServerEnabled
view.Version = node.Version
view.ExtVersion = node.ExtVersion
return view
+26 -5
View File
@@ -1,6 +1,7 @@
package service
import (
"encoding/json"
"errors"
"openflare/model"
"time"
@@ -146,24 +147,44 @@ func buildRelayDashboardSnapshot(node *model.Node, obs *model.NodeObservationFrp
}
totalProxies := 0
totalConnections := 0
clientCounts := 0
proxies := []RelayProxyStat{}
if obs != nil {
totalProxies = obs.FrpsProxyCount
totalConnections = obs.FrpsConnections
clientCounts = obs.FrpsClientCount
if obs.FrpsProxies != "" {
var decoded []RelayProxyStat
if err := json.Unmarshal([]byte(obs.FrpsProxies), &decoded); err == nil {
proxies = decoded
}
}
}
if totalProxies < 0 {
totalProxies = 0
}
onlineProxies := totalProxies
if node.RelayStatus != "healthy" {
onlineProxies = 0
onlineProxies := 0
for _, p := range proxies {
if p.Status == "online" {
onlineProxies++
}
}
// Fallback for backward compatibility
if len(proxies) == 0 {
onlineProxies = totalProxies
if node.RelayStatus != "healthy" {
onlineProxies = 0
}
}
return &RelayDashboardSnapshot{
TotalProxies: totalProxies,
OnlineProxies: onlineProxies,
OfflineProxies: totalProxies - onlineProxies,
Proxies: []RelayProxyStat{},
Proxies: proxies,
TotalConnections: maxInt(totalConnections, 0),
ClientCounts: 0,
ClientCounts: maxInt(clientCounts, 0),
}
}
+32 -18
View File
@@ -1,6 +1,7 @@
package service
import (
"encoding/json"
"errors"
"fmt"
"log/slog"
@@ -16,26 +17,29 @@ import (
// RelayHeartbeatPayload is the payload sent by OpenFlareRelay in each heartbeat.
type RelayHeartbeatPayload struct {
Version string `json:"version"`
ExtVersion string `json:"frp_version"`
RelayStatus string `json:"relay_status"`
FrpsConnCount int `json:"frps_connections"`
FrpsProxyCount int `json:"frps_proxy_count"`
Name string `json:"name"`
IP string `json:"ip"`
Profile *AgentNodeSystemProfile `json:"profile,omitempty"`
Snapshot *AgentNodeMetricSnapshot `json:"snapshot,omitempty"`
HealthEvents []AgentNodeHealthEvent `json:"health_events,omitempty"`
Version string `json:"version"`
ExtVersion string `json:"frp_version"`
RelayStatus string `json:"relay_status"`
FrpsConnCount int `json:"frps_connections"`
FrpsProxyCount int `json:"frps_proxy_count"`
FrpsClientCount int `json:"frps_client_count"`
FrpsProxies []RelayProxyStat `json:"frps_proxies,omitempty"`
Name string `json:"name"`
IP string `json:"ip"`
Profile *AgentNodeSystemProfile `json:"profile,omitempty"`
Snapshot *AgentNodeMetricSnapshot `json:"snapshot,omitempty"`
HealthEvents []AgentNodeHealthEvent `json:"health_events,omitempty"`
}
const relayFrpsUnhealthyEventType = "frps_unhealthy"
// RelayConfig is the frps configuration sent to the Relay.
type RelayConfig struct {
BindPort int `json:"bind_port"`
VhostHTTPPort int `json:"vhost_http_port"`
AuthToken string `json:"auth_token"`
LogLevel string `json:"log_level"`
BindPort int `json:"bind_port"`
VhostHTTPPort int `json:"vhost_http_port"`
AuthToken string `json:"auth_token"`
LogLevel string `json:"log_level"`
WebServerEnabled bool `json:"web_server_enabled"`
}
// RelaySettings contains runtime settings for the Relay.
@@ -148,11 +152,20 @@ func persistRelayHeartbeatObservability(nodeID string, payload RelayHeartbeatPay
HealthEvents: payload.HealthEvents,
}, reportedAt)
var proxiesJSON string
if len(payload.FrpsProxies) > 0 {
if data, err := json.Marshal(payload.FrpsProxies); err == nil {
proxiesJSON = string(data)
}
}
frpsObs := &model.NodeObservationFrps{
NodeID: nodeID,
CapturedAt: reportedAt,
FrpsConnections: payload.FrpsConnCount,
FrpsProxyCount: payload.FrpsProxyCount,
FrpsClientCount: payload.FrpsClientCount,
FrpsProxies: proxiesJSON,
}
_ = frpsObs.Insert()
}
@@ -162,10 +175,11 @@ func buildRelayConfig(node *model.Node) *RelayConfig {
return nil
}
return &RelayConfig{
BindPort: node.RelayBindPort,
VhostHTTPPort: node.RelayVhostHTTPPort,
AuthToken: node.RelayAuthToken,
LogLevel: "info",
BindPort: node.RelayBindPort,
VhostHTTPPort: node.RelayVhostHTTPPort,
AuthToken: node.RelayAuthToken,
LogLevel: "info",
WebServerEnabled: node.RelayWebServerEnabled,
}
}