Merge branch perfect-panel/master/server into develop

This commit is contained in:
EUForest
2025-12-11 23:53:32 +08:00
parent 5e46357104
commit 76ff9a658d
60 changed files with 1897 additions and 84 deletions
+15
View File
@@ -0,0 +1,15 @@
package report
const (
RegisterAPI = "/basic/register" // 模块注册接口
)
// RegisterResponse 模块注册响应参数
type RegisterResponse struct {
Code int `json:"code"` // 响应代码
Message string `json:"message"` // 响应信息
Data struct {
Success bool `json:"success"` // 注册是否成功
Message string `json:"message"` // 返回信息
} `json:"data"` // 响应数据
}
+113
View File
@@ -0,0 +1,113 @@
package report
import (
"fmt"
"net"
"os"
"github.com/go-resty/resty/v2"
"github.com/perfect-panel/server/pkg/constant"
"github.com/perfect-panel/server/pkg/logger"
"github.com/pkg/errors"
)
// FreePort returns a free TCP port by opening a listener on port 0.
func FreePort() (int, error) {
l, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
defer l.Close()
// Get the assigned port
addr := l.Addr().(*net.TCPAddr)
return addr.Port, nil
}
// ModulePort returns the module port from the environment variable or a free port.
func ModulePort() (int, error) {
// 从环境变量获取端口号
value, exists := os.LookupEnv("PPANEL_PORT")
if exists {
var port int
_, err := fmt.Sscanf(value, "%d", &port)
if err != nil {
return FreePort()
}
return port, nil
}
return FreePort()
}
// GatewayPort returns the gateway port from the environment variable or a free port.
func GatewayPort() (int, error) {
// 从环境变量获取端口号
value, exists := os.LookupEnv("GATEWAY_PORT")
if exists {
var port int
_, err := fmt.Sscanf(value, "%d", &port)
if err != nil {
logger.Errorf("Failed to parse GATEWAY_PORT: %v Value %s", err.Error(), value)
panic(err)
}
return port, nil
}
return 0, errors.New("could not determine gateway port")
}
// RegisterModule registers a module with the gateway.
func RegisterModule(port int) error {
// 从环境变量中读取网关模块端口
gatewayPort, err := GatewayPort()
if err != nil {
logger.Errorf("Failed to determine GATEWAY_PORT: %v", err)
return err
}
// 从环境变量中获取通讯密钥
value, exists := os.LookupEnv("SECRET_KEY")
if !exists {
panic("could not determine secret key")
}
var response RegisterResponse
client := resty.New().SetBaseURL(fmt.Sprintf("http://127.0.0.1:%d", gatewayPort))
result, err := client.R().SetHeader("Content-Type", "application/json").SetBody(RegisterServiceRequest{
Secret: value,
ProxyPath: "/api",
ServiceURL: fmt.Sprintf("http://127.0.0.1:%d", port),
Repository: constant.Repository,
HeartbeatURL: fmt.Sprintf("http://127.0.0.1:%d/v1/common/heartbeat", port),
ServiceName: constant.ServiceName,
ServiceVersion: constant.Version,
}).SetResult(&response).Post(RegisterAPI)
if err != nil {
logger.Errorf("Failed to register service: %v", err)
return err
}
if result.IsError() {
return errors.New("failed to register module: " + result.Status())
}
if !response.Data.Success {
logger.Infof("Result: %v", result.String())
return errors.New("failed to register module: " + response.Message)
}
logger.Infof("Module registered successfully: %s", response.Message)
return nil
}
// IsGatewayMode checks if the application is running in gateway mode.
// It returns true if GATEWAY_MODE is set to "true" and GATEWAY_PORT is valid.
func IsGatewayMode() bool {
value, exists := os.LookupEnv("GATEWAY_MODE")
if exists && value == "true" {
if _, err := GatewayPort(); err == nil {
return true
}
}
return false
}
+21
View File
@@ -0,0 +1,21 @@
package report
import (
"testing"
)
func TestFreePort(t *testing.T) {
port, err := FreePort()
if err != nil {
t.Fatalf("FreePort() error: %v", err)
}
t.Logf("FreePort: %v", port)
}
func TestModulePort(t *testing.T) {
port, err := ModulePort()
if err != nil {
t.Fatalf("ModulePort() error: %v", err)
}
t.Logf("ModulePort: %v", port)
}
+11
View File
@@ -0,0 +1,11 @@
package report
type RegisterServiceRequest struct {
Secret string `json:"secret"` // 通讯密钥
ProxyPath string `json:"proxy_path"` // 代理路径
ServiceURL string `json:"service_url"` // 服务地址
Repository string `json:"repository"` // 服务代码仓库
ServiceName string `json:"service_name"` // 服务名称
HeartbeatURL string `json:"heartbeat_url"` // 心跳检测地址
ServiceVersion string `json:"service_version"` // 服务版本
}