Skip to content

Commit e68048d

Browse files
committed
net/http: add SetPattern and Pattern in Request to return matched pattern info
SetPattern will parse string with parsePattern function. This allows third party frameworks set pattern info in requests. Pattern will return matched pattern string if it is set. Fixes golang#66405
1 parent ba9c445 commit e68048d

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/net/http/request.go

+36
Original file line numberDiff line numberDiff line change
@@ -1561,3 +1561,39 @@ func (r *Request) requiresHTTP1() bool {
15611561
return hasToken(r.Header.Get("Connection"), "upgrade") &&
15621562
ascii.EqualFold(r.Header.Get("Upgrade"), "websocket")
15631563
}
1564+
1565+
// SetPattern parses a string into a Pattern and set in Request.
1566+
// The string's syntax is
1567+
//
1568+
// [METHOD] [HOST]/[PATH]
1569+
//
1570+
// where:
1571+
// - METHOD is an HTTP method
1572+
// - HOST is a hostname
1573+
// - PATH consists of slash-separated segments, where each segment is either
1574+
// a literal or a wildcard of the form "{name}", "{name...}", or "{$}".
1575+
//
1576+
// METHOD, HOST and PATH are all optional; that is, the string can be "/".
1577+
// If METHOD is present, it must be followed by at least one space or tab.
1578+
// Wildcard names must be valid Go identifiers.
1579+
// The "{$}" and "{name...}" wildcard must occur at the end of PATH.
1580+
// PATH may end with a '/'.
1581+
// Wildcard names in a path must be distinct.
1582+
func (r *Request) SetPattern(s string) error {
1583+
pat, err := parsePattern(s)
1584+
if err != nil {
1585+
return err
1586+
}
1587+
r.pat = pat
1588+
return nil
1589+
}
1590+
1591+
// Pattern returns the pattern that matched this request, if the request
1592+
// resulted from matching a pattern registered on a ServeMux.
1593+
// Otherwise, it returns the empty string.
1594+
func (r *Request) Pattern() string {
1595+
if r.pat == nil {
1596+
return ""
1597+
}
1598+
return r.pat.str
1599+
}

src/net/http/request_test.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ func TestPathValueNoMatch(t *testing.T) {
15271527
}
15281528
}
15291529

1530-
func TestPathValue(t *testing.T) {
1530+
func TestPathValueAndPattern(t *testing.T) {
15311531
for _, test := range []struct {
15321532
pattern string
15331533
url string
@@ -1568,6 +1568,9 @@ func TestPathValue(t *testing.T) {
15681568
t.Errorf("%q, %q: got %q, want %q", test.pattern, name, got, want)
15691569
}
15701570
}
1571+
if r.Pattern() != test.pattern {
1572+
t.Errorf("pattern: got %s, want %s", r.Pattern(), test.pattern)
1573+
}
15711574
})
15721575
server := httptest.NewServer(mux)
15731576
defer server.Close()
@@ -1652,3 +1655,25 @@ func TestStatus(t *testing.T) {
16521655
}
16531656
}
16541657
}
1658+
1659+
func TestSetPattern(t *testing.T) {
1660+
patterns := []string{
1661+
"GET /",
1662+
"HEAD /test",
1663+
"/",
1664+
"/foo/bar",
1665+
"GET /foo/{b...}",
1666+
"GET /{f}",
1667+
}
1668+
1669+
req := new(Request)
1670+
for _, pattern := range patterns {
1671+
err := req.SetPattern(pattern)
1672+
if err != nil {
1673+
t.Fatal(err)
1674+
}
1675+
if req.Pattern() != pattern {
1676+
t.Errorf("pattern doesn't match, got %s, want %s", req.Pattern(), pattern)
1677+
}
1678+
}
1679+
}

0 commit comments

Comments
 (0)