Skip to content

Commit

Permalink
net/http: add SetPattern and Pattern in Request to return matched pat…
Browse files Browse the repository at this point in the history
…tern 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
  • Loading branch information
sillydong committed Apr 1, 2024
1 parent ba9c445 commit e68048d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
36 changes: 36 additions & 0 deletions src/net/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -1561,3 +1561,39 @@ func (r *Request) requiresHTTP1() bool {
return hasToken(r.Header.Get("Connection"), "upgrade") &&
ascii.EqualFold(r.Header.Get("Upgrade"), "websocket")
}

// SetPattern parses a string into a Pattern and set in Request.
// The string's syntax is
//
// [METHOD] [HOST]/[PATH]
//
// where:
// - METHOD is an HTTP method
// - HOST is a hostname
// - PATH consists of slash-separated segments, where each segment is either
// a literal or a wildcard of the form "{name}", "{name...}", or "{$}".
//
// METHOD, HOST and PATH are all optional; that is, the string can be "/".
// If METHOD is present, it must be followed by at least one space or tab.
// Wildcard names must be valid Go identifiers.
// The "{$}" and "{name...}" wildcard must occur at the end of PATH.
// PATH may end with a '/'.
// Wildcard names in a path must be distinct.
func (r *Request) SetPattern(s string) error {
pat, err := parsePattern(s)
if err != nil {
return err
}
r.pat = pat
return nil
}

// Pattern returns the pattern that matched this request, if the request
// resulted from matching a pattern registered on a ServeMux.
// Otherwise, it returns the empty string.
func (r *Request) Pattern() string {
if r.pat == nil {
return ""
}
return r.pat.str
}
27 changes: 26 additions & 1 deletion src/net/http/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,7 @@ func TestPathValueNoMatch(t *testing.T) {
}
}

func TestPathValue(t *testing.T) {
func TestPathValueAndPattern(t *testing.T) {
for _, test := range []struct {
pattern string
url string
Expand Down Expand Up @@ -1568,6 +1568,9 @@ func TestPathValue(t *testing.T) {
t.Errorf("%q, %q: got %q, want %q", test.pattern, name, got, want)
}
}
if r.Pattern() != test.pattern {
t.Errorf("pattern: got %s, want %s", r.Pattern(), test.pattern)
}
})
server := httptest.NewServer(mux)
defer server.Close()
Expand Down Expand Up @@ -1652,3 +1655,25 @@ func TestStatus(t *testing.T) {
}
}
}

func TestSetPattern(t *testing.T) {
patterns := []string{
"GET /",
"HEAD /test",
"/",
"/foo/bar",
"GET /foo/{b...}",
"GET /{f}",
}

req := new(Request)
for _, pattern := range patterns {
err := req.SetPattern(pattern)
if err != nil {
t.Fatal(err)
}
if req.Pattern() != pattern {
t.Errorf("pattern doesn't match, got %s, want %s", req.Pattern(), pattern)
}
}
}

0 comments on commit e68048d

Please sign in to comment.