diff --git a/mux.go b/mux.go index 91daf691..5e0a2812 100644 --- a/mux.go +++ b/mux.go @@ -476,6 +476,9 @@ func (mx *Mux) routeHTTP(w http.ResponseWriter, r *http.Request) { if supportsPathValue { setPathValue(rctx, r) } + if supportsPattern { + setPattern(rctx, r) + } h.ServeHTTP(w, r) return diff --git a/pattern.go b/pattern.go new file mode 100644 index 00000000..890a2c21 --- /dev/null +++ b/pattern.go @@ -0,0 +1,16 @@ +//go:build go1.23 && !tinygo +// +build go1.23,!tinygo + +package chi + +import "net/http" + +// supportsPattern is true if the Go version is 1.23 and above. +// +// If this is true, `net/http.Request` has field `Pattern`. +const supportsPattern = true + +// setPattern sets the mux matched pattern in the http Request. +func setPattern(rctx *Context, r *http.Request) { + r.Pattern = rctx.routePattern +} diff --git a/pattern_fallback.go b/pattern_fallback.go new file mode 100644 index 00000000..48a94ef8 --- /dev/null +++ b/pattern_fallback.go @@ -0,0 +1,17 @@ +//go:build !go1.23 || tinygo +// +build !go1.23 tinygo + +package chi + +import "net/http" + +// supportsPattern is true if the Go version is 1.23 and above. +// +// If this is true, `net/http.Request` has field `Pattern`. +const supportsPattern = false + +// setPattern sets the mux matched pattern in the http Request. +// +// setPattern is only supported in Go 1.23 and above so +// this is just a blank function so that it compiles. +func setPattern(rctx *Context, r *http.Request) {} diff --git a/pattern_test.go b/pattern_test.go new file mode 100644 index 00000000..bf8a3045 --- /dev/null +++ b/pattern_test.go @@ -0,0 +1,56 @@ +//go:build go1.23 +// +build go1.23 + +package chi + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestPattern(t *testing.T) { + testCases := []struct { + name string + pattern string + method string + requestPath string + }{ + { + name: "Basic path value", + pattern: "/hubs/{hubID}", + method: "GET", + requestPath: "/hubs/392", + }, + { + name: "Two path values", + pattern: "/users/{userID}/conversations/{conversationID}", + method: "POST", + requestPath: "/users/Gojo/conversations/2948", + }, + { + name: "Wildcard path", + pattern: "/users/{userID}/friends/*", + method: "POST", + requestPath: "/users/Gojo/friends/all-of-them/and/more", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + r := NewRouter() + + r.Handle(tc.method+" "+tc.pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(r.Pattern)) + })) + + ts := httptest.NewServer(r) + defer ts.Close() + + _, body := testRequest(t, ts, tc.method, tc.requestPath, nil) + if body != tc.pattern { + t.Fatalf("expecting %q, got %q", tc.pattern, body) + } + }) + } +}