Refactor: Avoid network requests when health check is disabled

This change ensures that when a site's health check is disabled, the checker returns cached metadata without making any network requests, as per issue #1446. A new helper function `getExistingSiteSnapshot` is introduced to retrieve this cached information. A new test case `TestCheckSiteSkipsNetworkWhenDisabled` is added to verify this behavior.

Co-authored-by: jacky-943572677 <jacky-943572677@qq.com>
This commit is contained in:
Cursor Agent
2025-11-25 11:22:21 +00:00
parent 39fc181bbf
commit 54d276447e
2 changed files with 74 additions and 11 deletions

View File

@@ -293,24 +293,25 @@ func (sc *SiteChecker) CheckSite(ctx context.Context, siteURL string) (*SiteInfo
// Try enhanced health check first if config exists
config, err := LoadSiteConfig(siteURL)
// If health check is disabled, return a SiteInfo without status
// If health check is disabled, return cached metadata without issuing any network requests (#1446)
if err == nil && config != nil && !config.HealthCheckEnabled {
protocol := "http"
if config.HealthCheckConfig != nil && config.HealthCheckConfig.Protocol != "" {
protocol = config.HealthCheckConfig.Protocol
}
siteInfo := &SiteInfo{
SiteConfig: *config,
Name: extractDomainName(siteURL),
Title: config.DisplayURL,
}
// Try to get favicon if enabled and not a gRPC check
if sc.options.CheckFavicon && !isGRPCProtocol(protocol) {
faviconURL, faviconData := sc.tryGetFavicon(ctx, siteURL)
siteInfo.FaviconURL = faviconURL
siteInfo.FaviconData = faviconData
if existing := sc.getExistingSiteSnapshot(siteURL); existing != nil {
siteInfo.FaviconURL = existing.FaviconURL
siteInfo.FaviconData = existing.FaviconData
siteInfo.Status = existing.Status
siteInfo.StatusCode = existing.StatusCode
siteInfo.ResponseTime = existing.ResponseTime
siteInfo.LastChecked = existing.LastChecked
siteInfo.Error = existing.Error
if siteInfo.Title == "" {
siteInfo.Title = existing.Title
}
}
return siteInfo, nil
@@ -522,6 +523,20 @@ func (sc *SiteChecker) GetSitesList() []*SiteInfo {
return result
}
// getExistingSiteSnapshot returns a copy of the last known site info, if present.
func (sc *SiteChecker) getExistingSiteSnapshot(siteURL string) *SiteInfo {
sc.mu.RLock()
defer sc.mu.RUnlock()
existing, ok := sc.sites[siteURL]
if !ok || existing == nil {
return nil
}
clone := *existing
return &clone
}
// extractDomainName extracts domain name from URL
func extractDomainName(siteURL string) string {
parsed, err := url.Parse(siteURL)

View File

@@ -0,0 +1,48 @@
package sitecheck
import (
"context"
"net/http"
"testing"
"github.com/0xJacky/Nginx-UI/model"
)
type roundTripFunc func(*http.Request) (*http.Response, error)
func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req)
}
func TestCheckSiteSkipsNetworkWhenDisabled(t *testing.T) {
t.Cleanup(InvalidateSiteConfigCache)
options := DefaultCheckOptions()
checker := NewSiteChecker(options)
// Any HTTP request made by the checker should fail this test.
checker.client = &http.Client{
Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) {
t.Fatalf("unexpected HTTP request to %s while health check is disabled", req.URL.String())
return nil, nil
}),
}
const siteURL = "https://example.com"
config := &model.SiteConfig{
Model: model.Model{ID: 1},
Host: "example.com:443",
Scheme: "https",
DisplayURL: siteURL,
HealthCheckEnabled: false,
HealthCheckConfig: &model.HealthCheckConfig{
Protocol: "https",
},
}
setCachedSiteConfig(config.Host, config)
if _, err := checker.CheckSite(context.Background(), siteURL); err != nil {
t.Fatalf("CheckSite returned error: %v", err)
}
}