Skip to content

Commit d12cc49

Browse files
authored
feat(mux): support http.Request.Pattern in Go 1.23 (#986)
Similar to #901 Adds support to get the pattern that was used by Chi to match the route, without needing to call the Chi context.
1 parent 1c2d011 commit d12cc49

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

mux.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ func (mx *Mux) routeHTTP(w http.ResponseWriter, r *http.Request) {
470470
if supportsPathValue {
471471
setPathValue(rctx, r)
472472
}
473+
if supportsPattern {
474+
setPattern(rctx, r)
475+
}
473476

474477
h.ServeHTTP(w, r)
475478
return

pattern.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build go1.23 && !tinygo
2+
// +build go1.23,!tinygo
3+
4+
package chi
5+
6+
import "net/http"
7+
8+
// supportsPattern is true if the Go version is 1.23 and above.
9+
//
10+
// If this is true, `net/http.Request` has field `Pattern`.
11+
const supportsPattern = true
12+
13+
// setPattern sets the mux matched pattern in the http Request.
14+
func setPattern(rctx *Context, r *http.Request) {
15+
r.Pattern = rctx.routePattern
16+
}

pattern_fallback.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//go:build !go1.23 || tinygo
2+
// +build !go1.23 tinygo
3+
4+
package chi
5+
6+
import "net/http"
7+
8+
// supportsPattern is true if the Go version is 1.23 and above.
9+
//
10+
// If this is true, `net/http.Request` has field `Pattern`.
11+
const supportsPattern = false
12+
13+
// setPattern sets the mux matched pattern in the http Request.
14+
//
15+
// setPattern is only supported in Go 1.23 and above so
16+
// this is just a blank function so that it compiles.
17+
func setPattern(rctx *Context, r *http.Request) {}

pattern_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//go:build go1.23
2+
// +build go1.23
3+
4+
package chi
5+
6+
import (
7+
"net/http"
8+
"net/http/httptest"
9+
"testing"
10+
)
11+
12+
func TestPattern(t *testing.T) {
13+
testCases := []struct {
14+
name string
15+
pattern string
16+
method string
17+
requestPath string
18+
}{
19+
{
20+
name: "Basic path value",
21+
pattern: "/hubs/{hubID}",
22+
method: "GET",
23+
requestPath: "/hubs/392",
24+
},
25+
{
26+
name: "Two path values",
27+
pattern: "/users/{userID}/conversations/{conversationID}",
28+
method: "POST",
29+
requestPath: "/users/Gojo/conversations/2948",
30+
},
31+
{
32+
name: "Wildcard path",
33+
pattern: "/users/{userID}/friends/*",
34+
method: "POST",
35+
requestPath: "/users/Gojo/friends/all-of-them/and/more",
36+
},
37+
}
38+
39+
for _, tc := range testCases {
40+
t.Run(tc.name, func(t *testing.T) {
41+
r := NewRouter()
42+
43+
r.Handle(tc.method+" "+tc.pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
44+
w.Write([]byte(r.Pattern))
45+
}))
46+
47+
ts := httptest.NewServer(r)
48+
defer ts.Close()
49+
50+
_, body := testRequest(t, ts, tc.method, tc.requestPath, nil)
51+
if body != tc.pattern {
52+
t.Fatalf("expecting %q, got %q", tc.pattern, body)
53+
}
54+
})
55+
}
56+
}

0 commit comments

Comments
 (0)