浏览代码

feat: add stub_status_port configuration for Nginx settings

Jacky 3 周之前
父节点
当前提交
509443a6e7

+ 4 - 4
api/nginx/router.go

@@ -13,13 +13,13 @@ func InitRouter(r *gin.RouterGroup) {
 	r.POST("nginx/restart", Restart)
 	r.POST("nginx/test", Test)
 	r.GET("nginx/status", Status)
-	// 获取 Nginx 详细状态信息,包括连接数、进程信息等(Issue #850)
+	// Get detailed Nginx status information, including connection count, process information, etc. (Issue #850)
 	r.GET("nginx/detail_status", GetDetailStatus)
-	// 使用SSE推送Nginx详细状态信息
+	// Use SSE to push detailed Nginx status information
 	r.GET("nginx/detail_status/stream", StreamDetailStatus)
-	// 获取 stub_status 模块状态
+	// Get stub_status module status
 	r.GET("nginx/stub_status", CheckStubStatus)
-	// 启用或禁用 stub_status 模块
+	// Enable or disable stub_status module
 	r.POST("nginx/stub_status", ToggleStubStatus)
 	r.POST("nginx_log", nginx_log.GetNginxLogPage)
 	r.GET("nginx/directives", GetDirectives)

+ 24 - 24
api/nginx/status.go

@@ -1,6 +1,6 @@
-// GetDetailedStatus API 实现
-// 该功能用于解决 Issue #850,提供类似宝塔面板的 Nginx 负载监控功能
-// 返回详细的 Nginx 状态信息,包括请求统计、连接数、工作进程等数据
+// Implementation of GetDetailedStatus API
+// This feature is designed to address Issue #850, providing Nginx load monitoring functionality similar to BT Panel
+// Returns detailed Nginx status information, including request statistics, connections, worker processes, and other data
 package nginx
 
 import (
@@ -15,79 +15,79 @@ import (
 	"github.com/uozi-tech/cosy/logger"
 )
 
-// NginxPerformanceInfo 存储 Nginx 性能相关信息
+// NginxPerformanceInfo stores Nginx performance-related information
 type NginxPerformanceInfo struct {
-	// 基本状态信息
+	// Basic status information
 	nginx.StubStatusData
 
-	// 进程相关信息
+	// Process-related information
 	nginx.NginxProcessInfo
 
-	// 配置信息
+	// Configuration information
 	nginx.NginxConfigInfo
 }
 
-// GetDetailStatus 获取 Nginx 详细状态信息
+// GetDetailStatus retrieves detailed Nginx status information
 func GetDetailStatus(c *gin.Context) {
 	response := nginx.GetPerformanceData()
 	c.JSON(http.StatusOK, response)
 }
 
-// StreamDetailStatus 使用 SSE 流式推送 Nginx 详细状态信息
+// StreamDetailStatus streams Nginx detailed status information using SSE
 func StreamDetailStatus(c *gin.Context) {
-	// 设置 SSE 的响应头
+	// Set SSE response headers
 	c.Header("Content-Type", "text/event-stream")
 	c.Header("Cache-Control", "no-cache")
 	c.Header("Connection", "keep-alive")
 	c.Header("Access-Control-Allow-Origin", "*")
 
-	// 创建上下文,当客户端断开连接时取消
+	// Create context that cancels when client disconnects
 	ctx := c.Request.Context()
 
-	// 为防止 goroutine 泄漏,创建一个计时器通道
+	// Create a ticker channel to prevent goroutine leaks
 	ticker := time.NewTicker(5 * time.Second)
 	defer ticker.Stop()
 
-	// 立即发送一次初始数据
+	// Send initial data immediately
 	sendPerformanceData(c)
 
-	// 使用 goroutine 定期发送数据
+	// Use goroutine to send data periodically
 	for {
 		select {
 		case <-ticker.C:
-			// 发送性能数据
+			// Send performance data
 			if err := sendPerformanceData(c); err != nil {
 				logger.Warn("Error sending SSE data:", err)
 				return
 			}
 		case <-ctx.Done():
-			// 客户端断开连接或请求被取消
+			// Client closed connection or request canceled
 			logger.Debug("Client closed connection")
 			return
 		}
 	}
 }
 
-// sendPerformanceData 发送一次性能数据
+// sendPerformanceData sends performance data once
 func sendPerformanceData(c *gin.Context) error {
 	response := nginx.GetPerformanceData()
 
-	// 发送 SSE 事件
+	// Send SSE event
 	c.SSEvent("message", response)
 
-	// 刷新缓冲区,确保数据立即发送
+	// Flush buffer to ensure data is sent immediately
 	c.Writer.Flush()
 	return nil
 }
 
-// CheckStubStatus 获取 Nginx stub_status 模块状态
+// CheckStubStatus gets Nginx stub_status module status
 func CheckStubStatus(c *gin.Context) {
 	stubStatus := nginx.GetStubStatus()
 
 	c.JSON(http.StatusOK, stubStatus)
 }
 
-// ToggleStubStatus 启用或禁用 stub_status 模块
+// ToggleStubStatus enables or disables stub_status module
 func ToggleStubStatus(c *gin.Context) {
 	var json struct {
 		Enable bool `json:"enable"`
@@ -99,7 +99,7 @@ func ToggleStubStatus(c *gin.Context) {
 
 	stubStatus := nginx.GetStubStatus()
 
-	// 如果当前状态与期望状态相同,则无需操作
+	// If current status matches desired status, no action needed
 	if stubStatus.Enabled == json.Enable {
 		c.JSON(http.StatusOK, stubStatus)
 		return
@@ -117,7 +117,7 @@ func ToggleStubStatus(c *gin.Context) {
 		return
 	}
 
-	// 重新加载 Nginx 配置
+	// Reload Nginx configuration
 	reloadOutput := nginx.Reload()
 	if len(reloadOutput) > 0 && (strings.Contains(strings.ToLower(reloadOutput), "error") ||
 		strings.Contains(strings.ToLower(reloadOutput), "failed")) {
@@ -125,7 +125,7 @@ func ToggleStubStatus(c *gin.Context) {
 		return
 	}
 
-	// 检查操作后的状态
+	// Check status after operation
 	newStubStatus := nginx.GetStubStatus()
 
 	c.JSON(http.StatusOK, newStubStatus)

+ 2 - 0
api/settings/settings.go

@@ -71,6 +71,7 @@ func SaveSettings(c *gin.Context) {
 		Node      settings.Node      `json:"node"`
 		Openai    settings.OpenAI    `json:"openai"`
 		Logrotate settings.Logrotate `json:"logrotate"`
+		Nginx     settings.Nginx     `json:"nginx"`
 	}
 
 	if !cosy.BindAndValid(c, &json) {
@@ -104,6 +105,7 @@ func SaveSettings(c *gin.Context) {
 	cSettings.ProtectedFill(settings.NodeSettings, &json.Node)
 	cSettings.ProtectedFill(settings.OpenAISettings, &json.Openai)
 	cSettings.ProtectedFill(settings.LogrotateSettings, &json.Logrotate)
+	cSettings.ProtectedFill(settings.NginxSettings, &json.Nginx)
 
 	err := settings.Save()
 	if err != nil {

+ 1 - 0
app/src/api/settings.ts

@@ -63,6 +63,7 @@ export interface NginxSettings {
   test_config_cmd: string
   reload_cmd: string
   restart_cmd: string
+  stub_status_port: number
 }
 
 export interface NodeSettings {

+ 3 - 0
app/src/views/preference/NginxSettings.vue

@@ -6,6 +6,9 @@ const data: Ref<Settings> = inject('data') as Ref<Settings>
 
 <template>
   <AForm layout="vertical">
+    <AFormItem :label="$gettext('Stub Status Port')">
+      <AInputNumber v-model:value="data.nginx.stub_status_port" />
+    </AFormItem>
     <AFormItem :label="$gettext('Nginx Access Log Path')">
       {{ data.nginx.access_log_path }}
     </AFormItem>

+ 1 - 0
app/src/views/preference/Preference.vue

@@ -74,6 +74,7 @@ const data = ref<Settings>({
     test_config_cmd: '',
     reload_cmd: '',
     restart_cmd: '',
+    stub_status_port: 51820,
   },
   node: {
     name: '',

+ 1 - 1
internal/nginx/performance.go

@@ -43,7 +43,7 @@ func GetPerformanceData() NginxPerformanceResponse {
 		logger.Warn("Failed to get Nginx config info:", err)
 	}
 
-	// 确保ProcessMode字段能够正确传递
+	// Ensure ProcessMode field is correctly passed
 	perfInfo := NginxPerformanceInfo{
 		StubStatusData:   *statusInfo,
 		NginxProcessInfo: *processInfo,

+ 44 - 11
internal/nginx/stub_status.go

@@ -1,6 +1,7 @@
 package nginx
 
 import (
+	"bytes"
 	"fmt"
 	"io"
 	"net/http"
@@ -8,8 +9,10 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+	"text/template"
 	"time"
 
+	"github.com/0xJacky/Nginx-UI/settings"
 	"github.com/pkg/errors"
 	"github.com/uozi-tech/cosy/logger"
 )
@@ -31,7 +34,6 @@ type StubStatusData struct {
 }
 
 const (
-	StubStatusPort       = 51828
 	StubStatusPath       = "/stub_status"
 	StubStatusHost       = "127.0.0.1"
 	StubStatusProtocol   = "http"
@@ -54,7 +56,7 @@ func GetStubStatusData() (bool, *StubStatusData, error) {
 
 	// Get the stub_status status information
 	enabled, statusURL := IsStubStatusEnabled()
-	logger.Info("GetStubStatusData", "enabled", enabled, "statusURL", statusURL)
+	logger.Debug("GetStubStatusData", "enabled", enabled, "statusURL", statusURL)
 	if !enabled {
 		return false, result, fmt.Errorf("stub_status is not enabled")
 	}
@@ -131,12 +133,12 @@ func IsStubStatusEnabled() (bool, string) {
 	for _, server := range ngxConfig.Servers {
 		protocol := StubStatusProtocol
 		host := StubStatusHost
-		port := strconv.Itoa(StubStatusPort)
+		port := settings.NginxSettings.StubStatusPort
 
 		for _, location := range server.Locations {
 			// Check if the location content contains stub_status
 			if strings.Contains(location.Content, "stub_status") {
-				stubStatusURL := fmt.Sprintf("%s://%s:%s%s", protocol, host, port, StubStatusPath)
+				stubStatusURL := fmt.Sprintf("%s://%s:%d%s", protocol, host, port, StubStatusPath)
 				return true, stubStatusURL
 			}
 		}
@@ -169,23 +171,54 @@ func DisableStubStatus() error {
 func CreateStubStatusConfig() error {
 	httpConfPath := GetConfPath("conf.d", StubStatusConfigName)
 
-	stubStatusConfig := `
+	const stubStatusTemplate = `
 # DO NOT EDIT THIS FILE, IT IS AUTO GENERATED BY NGINX-UI
 # Nginx stub_status configuration for Nginx-UI
-# Modified at ` + time.Now().Format("2006-01-02 15:04:05") + `
+# Modified at {{.ModifiedTime}}
 
 server {
-    listen 51828;  # Use non-standard port to avoid conflicts
-    server_name localhost;
+    listen {{.Port}};  # Use non-standard port to avoid conflicts
+    server_name {{.ServerName}};
 
     # Status monitoring interface
-    location /stub_status {
+    location {{.StatusPath}} {
         stub_status;
-        allow 127.0.0.1; # Only allow local access
-        deny all;
+        allow {{.AllowIP}}; # Only allow local access
+        deny {{.DenyAccess}};
     }
 }
 `
+
+	type StubStatusTemplateData struct {
+		ModifiedTime string
+		Port         uint
+		ServerName   string
+		StatusPath   string
+		AllowIP      string
+		DenyAccess   string
+	}
+
+	data := StubStatusTemplateData{
+		ModifiedTime: time.Now().Format(time.DateTime),
+		Port:         settings.NginxSettings.StubStatusPort,
+		ServerName:   "localhost",
+		StatusPath:   StubStatusPath,
+		AllowIP:      StubStatusAllow,
+		DenyAccess:   StubStatusDeny,
+	}
+
+	tmpl, err := template.New("stub_status").Parse(stubStatusTemplate)
+	if err != nil {
+		return errors.Wrap(err, "failed to parse template")
+	}
+
+	var buf bytes.Buffer
+	if err := tmpl.Execute(&buf, data); err != nil {
+		return errors.Wrap(err, "failed to execute template")
+	}
+
+	stubStatusConfig := buf.String()
+
 	ngxConfig, err := ParseNgxConfigByContent(stubStatusConfig)
 	if err != nil {
 		return errors.Wrap(err, "failed to parse new nginx config")

+ 8 - 0
settings/nginx.go

@@ -10,6 +10,14 @@ type Nginx struct {
 	TestConfigCmd   string   `json:"test_config_cmd" protected:"true"`
 	ReloadCmd       string   `json:"reload_cmd" protected:"true"`
 	RestartCmd      string   `json:"restart_cmd" protected:"true"`
+	StubStatusPort  uint     `json:"stub_status_port" binding:"omitempty,min=1,max=65535"`
 }
 
 var NginxSettings = &Nginx{}
+
+func (n *Nginx) GetStubStatusPort() uint {
+	if n.StubStatusPort == 0 {
+		return 51820
+	}
+	return n.StubStatusPort
+}