feat(managementasset): enforce 3-hour rate limit on management asset update checks

- Introduced synchronization with `sync.Mutex` to ensure thread safety.
- Added logic to skip update checks if the last check was performed within the 3-hour interval.
This commit is contained in:
Luis Pater
2025-10-10 04:23:58 +08:00
parent 11f090c223
commit 57195fa0f5

View File

@@ -12,6 +12,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"time" "time"
"github.com/router-for-me/CLIProxyAPI/v6/internal/util" "github.com/router-for-me/CLIProxyAPI/v6/internal/util"
@@ -23,11 +24,17 @@ const (
managementReleaseURL = "https://api.github.com/repos/router-for-me/Cli-Proxy-API-Management-Center/releases/latest" managementReleaseURL = "https://api.github.com/repos/router-for-me/Cli-Proxy-API-Management-Center/releases/latest"
managementAssetName = "management.html" managementAssetName = "management.html"
httpUserAgent = "CLIProxyAPI-management-updater" httpUserAgent = "CLIProxyAPI-management-updater"
updateCheckInterval = 3 * time.Hour
) )
// ManagementFileName exposes the control panel asset filename. // ManagementFileName exposes the control panel asset filename.
const ManagementFileName = managementAssetName const ManagementFileName = managementAssetName
var (
lastUpdateCheckMu sync.Mutex
lastUpdateCheckTime time.Time
)
func newHTTPClient(proxyURL string) *http.Client { func newHTTPClient(proxyURL string) *http.Client {
client := &http.Client{Timeout: 15 * time.Second} client := &http.Client{Timeout: 15 * time.Second}
@@ -68,6 +75,7 @@ func FilePath(configFilePath string) string {
// EnsureLatestManagementHTML checks the latest management.html asset and updates the local copy when needed. // EnsureLatestManagementHTML checks the latest management.html asset and updates the local copy when needed.
// The function is designed to run in a background goroutine and will never panic. // The function is designed to run in a background goroutine and will never panic.
// It enforces a 3-hour rate limit to avoid frequent checks on config/auth file changes.
func EnsureLatestManagementHTML(ctx context.Context, staticDir string, proxyURL string) { func EnsureLatestManagementHTML(ctx context.Context, staticDir string, proxyURL string) {
if ctx == nil { if ctx == nil {
ctx = context.Background() ctx = context.Background()
@@ -79,6 +87,18 @@ func EnsureLatestManagementHTML(ctx context.Context, staticDir string, proxyURL
return return
} }
// Rate limiting: check only once every 3 hours
lastUpdateCheckMu.Lock()
now := time.Now()
timeSinceLastCheck := now.Sub(lastUpdateCheckTime)
if timeSinceLastCheck < updateCheckInterval {
lastUpdateCheckMu.Unlock()
log.Debugf("management asset update check skipped: last check was %v ago (interval: %v)", timeSinceLastCheck.Round(time.Second), updateCheckInterval)
return
}
lastUpdateCheckTime = now
lastUpdateCheckMu.Unlock()
if err := os.MkdirAll(staticDir, 0o755); err != nil { if err := os.MkdirAll(staticDir, 0o755); err != nil {
log.WithError(err).Warn("failed to prepare static directory for management asset") log.WithError(err).Warn("failed to prepare static directory for management asset")
return return