From e359407fd0e2487abc3c823134500df5ce0b54ad Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Wed, 20 Nov 2019 09:57:11 +0800 Subject: [PATCH] Add Cookies and CookiesRegexp to Router --- mux.go | 6 +++++ route.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/mux.go b/mux.go index c9ba647..3a4a27b 100644 --- a/mux.go +++ b/mux.go @@ -306,6 +306,12 @@ func (r *Router) Headers(pairs ...string) *Route { return r.NewRoute().Headers(pairs...) } +// Cookies registers a new route with a matcher for request cookie values. +// See Route.Cookies(). +func (r *Router) Cookies(pairs ...string) *Route { + return r.NewRoute().Cookies(pairs...) +} + // Host registers a new route with a matcher for the URL host. // See Route.Host(). func (r *Router) Host(tpl string) *Route { diff --git a/route.go b/route.go index 750afe5..cd9984b 100644 --- a/route.go +++ b/route.go @@ -218,6 +218,73 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { return nil } +// Cookies +// cookieMatcher matches the request against cookie values. +type cookieMatcher map[string]string + +func (c cookieMatcher) Match(r *http.Request, match *RouteMatch) bool { + values := map[string][]string{} + for name := range c { + c_, err := r.Cookie(name) + if err != nil { + return false + } + values[name] = []string{c_.Value} + } + return matchMapWithString(c, values, false) +} + +// Cookies adds a matcher for request cookie values. +// It accepts a sequence of key/value pairs to be matched. For example: +// +// r := mux.NewRouter() +// r.Cookie("user-role", "test-a") +// +// The above route will only match if both request cookie values match. +// If the value is an empty string, it will match any value if the key is set. +func (r *Route) Cookies(pairs ...string) *Route { + if r.err == nil { + var cookies map[string]string + cookies, r.err = mapFromPairsToString(pairs...) + return r.addMatcher(cookieMatcher(cookies)) + } + return r +} + +// cookieRegexMatcher matches the request against the route given a regex for the cookie +type cookieRegexMatcher map[string]*regexp.Regexp + +func (c cookieRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { + + values := map[string][]string{} + for name := range c { + c_, err := r.Cookie(name) + if err != nil { + return false + } + values[name] = []string{c_.Value} + } + return matchMapWithRegex(c, values, false) +} + +// CookiesRegexp accepts a sequence of key/value pairs, where the value has regex +// support. For example: +// +// r := mux.NewRouter() +// r.CookiesRegexp("user-role", "(test-a|test-b)") +// +// The above route will only match if both the request cookie matches both regular expressions. +// If the value is an empty string, it will match any value if the key is set. +// Use the start and end of string anchors (^ and $) to match an exact value. +func (r *Route) CookiesRegexp(pairs ...string) *Route { + if r.err == nil { + var cookies map[string]*regexp.Regexp + cookies, r.err = mapFromPairsToRegex(pairs...) + return r.addMatcher(cookieRegexMatcher(cookies)) + } + return r +} + // Headers -------------------------------------------------------------------- // headerMatcher matches the request against header values.