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.
This commit is contained in:
Chris Lu
2026-06-22 10:20:02 -07:00
committed by GitHub
parent 78288b39c9
commit 16ba8af0b7
+13 -3
View File
@@ -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
}