aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/request.go
diff options
context:
space:
mode:
authorJonathan Amsterdam <jba@google.com>2023-09-13 16:58:24 -0400
committerJonathan Amsterdam <jba@google.com>2023-09-14 00:00:28 +0000
commit495830acd6976c8a2b39dd4aa4fdc105ad72de52 (patch)
treea44f8bcbd8d75e67e2cd3ce5c607a6cbacde1616 /src/net/http/request.go
parentfccd0b9b70255099691deca5dc1d577efcfc889b (diff)
downloadgo-495830acd6976c8a2b39dd4aa4fdc105ad72de52.tar.xz
net/http: implement path value methods on Request
Add Request.PathValue and Request.SetPathValue, and the fields on Request required to support them. Populate those fields in ServeMux.ServeHTTP. Updates #61410. Change-Id: Ic88cb865b0d865a30d3b35ece8e0382c58ef67d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/528355 Run-TryBot: Jonathan Amsterdam <jba@google.com> Reviewed-by: Damien Neil <dneil@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/net/http/request.go')
-rw-r--r--src/net/http/request.go47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/net/http/request.go b/src/net/http/request.go
index 12039c9ae2..b66e6853f6 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -329,6 +329,11 @@ type Request struct {
// It is unexported to prevent people from using Context wrong
// and mutating the contexts held by callers of the same request.
ctx context.Context
+
+ // The following fields are for requests matched by ServeMux.
+ pat *pattern // the pattern that matched
+ matches []string // values for the matching wildcards in pat
+ otherValues map[string]string // for calls to SetPathValue that don't match a wildcard
}
// Context returns the request's context. To change the context, use
@@ -1415,6 +1420,48 @@ func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, e
return nil, nil, ErrMissingFile
}
+// PathValue returns the value for the named path wildcard in the ServeMux pattern
+// that matched the request.
+// It returns the empty string if the request was not matched against a pattern
+// or there is no such wildcard in the pattern.
+func (r *Request) PathValue(name string) string {
+ if i := r.patIndex(name); i >= 0 {
+ return r.matches[i]
+ }
+ return r.otherValues[name]
+}
+
+func (r *Request) SetPathValue(name, value string) {
+ if i := r.patIndex(name); i >= 0 {
+ r.matches[i] = value
+ } else {
+ if r.otherValues == nil {
+ r.otherValues = map[string]string{}
+ }
+ r.otherValues[name] = value
+ }
+}
+
+// patIndex returns the index of name in the list of named wildcards of the
+// request's pattern, or -1 if there is no such name.
+func (r *Request) patIndex(name string) int {
+ // The linear search seems expensive compared to a map, but just creating the map
+ // takes a lot of time, and most patterns will just have a couple of wildcards.
+ if r.pat == nil {
+ return -1
+ }
+ i := 0
+ for _, seg := range r.pat.segments {
+ if seg.wild && seg.s != "" {
+ if name == seg.s {
+ return i
+ }
+ i++
+ }
+ }
+ return -1
+}
+
func (r *Request) expectsContinue() bool {
return hasToken(r.Header.get("Expect"), "100-continue")
}