From 16ba8af0b77f8de25113fd90a289a43a06957eba Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Mon, 22 Jun 2026 10:20:02 -0700 Subject: [PATCH] util/http: lazily init the global HTTP client to fix admin metrics nil panic (#10044) util/http: lazily init the global HTTP client GetGlobalHttpClient returned a nil client until InitGlobalHttpClient ran, which only happens in weed.go's main. Anything that starts a command in-process bypasses that: the admin server's metrics goroutine seeds a dashboard sample on startup, reaching fetchPublicUrlMap -> GetGlobalHttpClient().Do, and nil-derefs the receiver in GetHttpScheme. Init the client on first Get via sync.Once so it is never nil regardless of the startup path. InitGlobalHttpClient keeps its eager-init role through the same Once. --- weed/util/http/http_global_client_init.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/weed/util/http/http_global_client_init.go b/weed/util/http/http_global_client_init.go index 0dcb05cfd..43fecf1d4 100644 --- a/weed/util/http/http_global_client_init.go +++ b/weed/util/http/http_global_client_init.go @@ -1,27 +1,37 @@ package http import ( + "sync" + "github.com/seaweedfs/seaweedfs/weed/glog" util_http_client "github.com/seaweedfs/seaweedfs/weed/util/http/client" ) var ( - globalHttpClient *util_http_client.HTTPClient + globalHttpClient *util_http_client.HTTPClient + globalHttpClientOnce sync.Once ) func NewGlobalHttpClient(opt ...util_http_client.HttpClientOpt) (*util_http_client.HTTPClient, error) { return util_http_client.NewHttpClient(util_http_client.Client, opt...) } +// GetGlobalHttpClient returns the process-wide HTTP client, initializing it on +// first use. Lazy init keeps callers that bypass weed.go's main (in-process +// test harnesses, libraries) from dereferencing a nil client. func GetGlobalHttpClient() *util_http_client.HTTPClient { + globalHttpClientOnce.Do(initGlobalHttpClient) return globalHttpClient } func InitGlobalHttpClient() { - var err error + globalHttpClientOnce.Do(initGlobalHttpClient) +} - globalHttpClient, err = NewGlobalHttpClient() +func initGlobalHttpClient() { + client, err := NewGlobalHttpClient() if err != nil { glog.Fatalf("error init global http client: %v", err) } + globalHttpClient = client }