From 4e62095245005b17f290dd1e4d9afe983df180ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 7 Jul 2026 20:52:36 +0200 Subject: [PATCH] core: preserve metrics registry in Context.WithValue (#7861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * core: preserve metrics registry in Context.WithValue Context.WithValue rebuilt the Context without copying the unexported metricsRegistry field, so any module provisioned under a context derived via WithValue saw a nil registry from GetMetricsRegistry(). * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Kévin Dunglas --------- Signed-off-by: Kévin Dunglas Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- context.go | 1 + context_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/context.go b/context.go index f71d635e2..7c06d26c0 100644 --- a/context.go +++ b/context.go @@ -676,6 +676,7 @@ func (ctx *Context) WithValue(key, value any) Context { ancestry: ctx.ancestry, cleanupFuncs: ctx.cleanupFuncs, exitFuncs: ctx.exitFuncs, + metricsRegistry: ctx.metricsRegistry, } } diff --git a/context_test.go b/context_test.go index 27395612c..1c1e2e062 100644 --- a/context_test.go +++ b/context_test.go @@ -15,10 +15,28 @@ package caddy import ( + "context" "encoding/json" "io" + "testing" ) +func TestContextWithValuePreservesMetricsRegistry(t *testing.T) { + ctx, cancel := NewContext(Context{Context: context.Background()}) + t.Cleanup(cancel) + + reg := ctx.GetMetricsRegistry() + if reg == nil { + t.Fatal("expected a metrics registry on the base context") + } + + type testKey struct{} + derived := ctx.WithValue(testKey{}, "value") + if got := derived.GetMetricsRegistry(); got != reg { + t.Fatalf("WithValue must preserve the metrics registry: got %p, want %p", got, reg) + } +} + func ExampleContext_LoadModule() { // this whole first part is just setting up for the example; // note the struct tags - very important; we specify inline_key