Skip to content

http: set r.Pattern on dispatched requests for automatic route tagging#3897

Merged
raphael merged 1 commit intov3from
fix/mux-set-request-pattern
Feb 16, 2026
Merged

http: set r.Pattern on dispatched requests for automatic route tagging#3897
raphael merged 1 commit intov3from
fix/mux-set-request-pattern

Conversation

@raphael
Copy link
Copy Markdown
Member

@raphael raphael commented Feb 16, 2026

Summary

The default HTTP muxer now populates r.Pattern with "METHOD /path" on every dispatched request, following the Go 1.22+ convention established by http.ServeMux.

This enables observability middleware such as otelhttp (v0.65.0+) to automatically tag spans and metrics with the matched route — no per-handler wrapping required.

Problem

The otelhttp package removed WithRouteTag in v0.65.0, breaking the otel plugin which generated calls to that function. The upstream replacement is r.Pattern — otelhttp now reads it automatically after handler dispatch.

Since Goa uses a Chi-based muxer (not http.ServeMux), r.Pattern was never set, so otelhttp couldn't pick up the route.

Solution

A single change in mux.Handle: capture the original Goa pattern before Chi's wildcard rewriting and set r.Pattern inside the handler wrapper:

reqPattern := method + " " + pattern
// ... wildcard rewriting ...
m.Method(method, pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    r.Pattern = reqPattern
    handler(w, r)
}))

Benefits over the old plugin approach:

  • One place instead of N per-handler wrappers
  • Covers all handlers uniformly — endpoints and file servers alike (the plugin only covered endpoints)
  • No fragile template string surgery in a plugin
  • Zero otelhttp dependency in generated or framework code — pure Go stdlib r.Pattern

The otel plugin has been deprecated in goadesign/plugins#242.

Fixes #3896

Test plan

  • New TestRequestPattern — verifies r.Pattern is set correctly for simple paths, parameterized segments (/users/{id}), and wildcards (/files/{*path})
  • All existing mux tests pass (TestMiddlewares, TestVars, TestResolvePattern)
  • go test ./http/ green

The default HTTP muxer now populates r.Pattern with "METHOD /path" on
every matched request, following the Go 1.22+ convention established by
http.ServeMux. This enables observability middleware such as otelhttp
(v0.65.0+) to automatically tag spans and metrics with the matched
route without any per-handler wrapping.

The pattern is captured before chi's internal wildcard rewriting, so
r.Pattern always reflects the original Goa route (e.g. GET /users/{id},
GET /files/{*path}).

This replaces the need for the otel plugin in goa.design/plugins which
has been deprecated (goadesign/plugins#242).

Fixes #3896
@raphael raphael merged commit 73c4ecd into v3 Feb 16, 2026
7 checks passed
@raphael raphael deleted the fix/mux-set-request-pattern branch February 16, 2026 19:16
JoaoBraveCoding added a commit to JoaoBraveCoding/api that referenced this pull request Feb 24, 2026
philipgough pushed a commit to observatorium/api that referenced this pull request Feb 26, 2026
* chore: update dependencies

* fix race condition

* chore: updated bingo tools

* fix: move from the deprecated CFB to CTR

* chore: updated some go expressions to recent standards

* refactor: stop using deprecated WithRouteTag
It was removed in open-telemetry/opentelemetry-go-contrib#8268
Approach was inspired by goadesign/goa#3897

* downgrade golangci-ling to 2.8.0 as it's the most recent version still
on 1.24

* update github.com/efficientgo/e2e
Copilot AI pushed a commit to observatorium/api that referenced this pull request Feb 26, 2026
* chore: update dependencies

* fix race condition

* chore: updated bingo tools

* fix: move from the deprecated CFB to CTR

* chore: updated some go expressions to recent standards

* refactor: stop using deprecated WithRouteTag
It was removed in open-telemetry/opentelemetry-go-contrib#8268
Approach was inspired by goadesign/goa#3897

* downgrade golangci-ling to 2.8.0 as it's the most recent version still
on 1.24

* update github.com/efficientgo/e2e
philipgough pushed a commit to rhobs/api that referenced this pull request Apr 10, 2026
* chore: update dependencies

* fix race condition

* chore: updated bingo tools

* fix: move from the deprecated CFB to CTR

* chore: updated some go expressions to recent standards

* refactor: stop using deprecated WithRouteTag
It was removed in open-telemetry/opentelemetry-go-contrib#8268
Approach was inspired by goadesign/goa#3897

* downgrade golangci-ling to 2.8.0 as it's the most recent version still
on 1.24

* update github.com/efficientgo/e2e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

otelhttp v0.65.0 removed WithRouteTag

1 participant