From e40bd019ff4599b34769d249ee37934217ed9fa4 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Wed, 14 Jan 2026 03:06:16 +0300 Subject: [PATCH] caddyfile: add `observe_catchall_hosts` option (#7434) * caddyfile: add `observe_catchall_hosts` option Signed-off-by: Mohammed Al Sahaf * correct JSON field name and doc comment Signed-off-by: Mohammed Al Sahaf --------- Signed-off-by: Mohammed Al Sahaf --- caddyconfig/httpcaddyfile/options.go | 2 ++ modules/caddyhttp/metrics.go | 6 +++--- modules/caddyhttp/metrics_test.go | 32 ++++++++++++++-------------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go index 336c6999f..58a75e9a2 100644 --- a/caddyconfig/httpcaddyfile/options.go +++ b/caddyconfig/httpcaddyfile/options.go @@ -472,6 +472,8 @@ func unmarshalCaddyfileMetricsOptions(d *caddyfile.Dispenser) (any, error) { switch d.Val() { case "per_host": metrics.PerHost = true + case "observe_catchall_hosts": + metrics.ObserveCatchallHosts = true default: return nil, d.Errf("unrecognized servers option '%s'", d.Val()) } diff --git a/modules/caddyhttp/metrics.go b/modules/caddyhttp/metrics.go index 424170732..8b4d380f0 100644 --- a/modules/caddyhttp/metrics.go +++ b/modules/caddyhttp/metrics.go @@ -25,7 +25,7 @@ import ( // "http": { // "metrics": { // "per_host": true, -// "allow_catch_all_hosts": false +// "observe_catchall_hosts": false // }, // "servers": { // "srv0": { @@ -65,7 +65,7 @@ type Metrics struct { // // Set to true to allow all hosts to get individual metrics (NOT RECOMMENDED // for production environments exposed to the internet). - AllowCatchAllHosts bool `json:"allow_catch_all_hosts,omitempty"` + ObserveCatchallHosts bool `json:"observe_catchall_hosts,omitempty"` init sync.Once httpMetrics *httpMetrics @@ -200,7 +200,7 @@ func (m *Metrics) shouldAllowHostMetrics(host string, isHTTPS bool) bool { } // For catch-all requests (not in allowed hosts) - allowCatchAll := m.AllowCatchAllHosts || (isHTTPS && m.hasHTTPSServer) + allowCatchAll := m.ObserveCatchallHosts || (isHTTPS && m.hasHTTPSServer) return allowCatchAll } diff --git a/modules/caddyhttp/metrics_test.go b/modules/caddyhttp/metrics_test.go index 9f6f59858..58b6a09ad 100644 --- a/modules/caddyhttp/metrics_test.go +++ b/modules/caddyhttp/metrics_test.go @@ -207,11 +207,11 @@ func TestMetricsInstrumentedHandler(t *testing.T) { func TestMetricsInstrumentedHandlerPerHost(t *testing.T) { ctx, _ := caddy.NewContext(caddy.Context{Context: context.Background()}) metrics := &Metrics{ - PerHost: true, - AllowCatchAllHosts: true, // Allow all hosts for testing - init: sync.Once{}, - httpMetrics: &httpMetrics{}, - allowedHosts: make(map[string]struct{}), + PerHost: true, + ObserveCatchallHosts: true, // Allow all hosts for testing + init: sync.Once{}, + httpMetrics: &httpMetrics{}, + allowedHosts: make(map[string]struct{}), } handlerErr := errors.New("oh noes") response := []byte("hello world!") @@ -387,11 +387,11 @@ func TestMetricsCardinalityProtection(t *testing.T) { // Test 1: Without AllowCatchAllHosts, arbitrary hosts should be mapped to "_other" metrics := &Metrics{ - PerHost: true, - AllowCatchAllHosts: false, // Default - should map unknown hosts to "_other" - init: sync.Once{}, - httpMetrics: &httpMetrics{}, - allowedHosts: make(map[string]struct{}), + PerHost: true, + ObserveCatchallHosts: false, // Default - should map unknown hosts to "_other" + init: sync.Once{}, + httpMetrics: &httpMetrics{}, + allowedHosts: make(map[string]struct{}), } // Add one allowed host @@ -444,12 +444,12 @@ func TestMetricsHTTPSCatchAll(t *testing.T) { // Test that HTTPS requests allow catch-all even when AllowCatchAllHosts is false metrics := &Metrics{ - PerHost: true, - AllowCatchAllHosts: false, - hasHTTPSServer: true, // Simulate having HTTPS servers - init: sync.Once{}, - httpMetrics: &httpMetrics{}, - allowedHosts: make(map[string]struct{}), // Empty - no explicitly allowed hosts + PerHost: true, + ObserveCatchallHosts: false, + hasHTTPSServer: true, // Simulate having HTTPS servers + init: sync.Once{}, + httpMetrics: &httpMetrics{}, + allowedHosts: make(map[string]struct{}), // Empty - no explicitly allowed hosts } mh := middlewareHandlerFunc(func(w http.ResponseWriter, r *http.Request, h Handler) error {