Skip to content

Commit

Permalink
Added regex matcher & test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
donutloop committed Dec 3, 2016
1 parent 9cec2bc commit 7f1c154
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 4 deletions.
29 changes: 29 additions & 0 deletions matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ type Matcher interface {
// headerMatcher matches the request against header values.
type headerMatcher map[string]comparison

func newHeaderMatcher(pairs ...string) (headerMatcher, error) {
headers, err := convertStringsToMapString(isEvenPairs, pairs...)
if err != nil {
return nil, err
}

return headerMatcher(headers), nil
}

func (m headerMatcher) Match(r *http.Request) bool {
return matchMap(m, r.Header, true)
}
Expand All @@ -29,6 +38,26 @@ func (m headerMatcher) Rank() int {
return rankAny
}

// headerRegexMatcher matches the request against header values.
type headerRegexMatcher map[string]comparison

func newHeaderRegexMatcher(pairs ...string) (headerRegexMatcher, error) {
headers, err := convertStringsToMapRegex(isEvenPairs, pairs...)
if err != nil {
return nil, err
}

return headerRegexMatcher(headers), nil
}

func (m headerRegexMatcher) Match(r *http.Request) bool {
return matchMap(m, r.Header, true)
}

func (m headerRegexMatcher) Rank() int {
return rankAny
}

// MatcherFunc is the function signature used by custom matchers.
type MatcherFunc func(*http.Request) bool

Expand Down
53 changes: 53 additions & 0 deletions matcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,56 @@ func TestMatcherFuncFail(t *testing.T) {
t.Errorf("Unexpected matched")
}
}

func TestHeaderMatcher(t *testing.T) {

tests := []struct {
m func(pairs ...string) (Matcher, error)
req func() *http.Request
pairs []string
}{
{
m: func(pairs ...string) (Matcher, error) {
return newHeaderMatcher(pairs...)
},
req: func() *http.Request {

req := &http.Request{
Header: http.Header{},
}
req.Header.Add("content-type", "applcation/json")

return req
},
pairs: []string{"content-type", "applcation/json"},
},
{
m: func(pairs ...string) (Matcher, error) {
return newHeaderRegexMatcher(pairs...)
},
req: func() *http.Request {

req := &http.Request{
Header: http.Header{},
}
req.Header.Add("content-type", "applcation/json")

return req
},
pairs: []string{"content-type", "applcation/(json|html)"},
},
}

for _, test := range tests {
matcher, err := test.m()

if err != nil {
t.Errorf("Unexpected error (%s)", err.Error())
}

req := test.req()
if !matcher.Match(req) {
t.Errorf("Unexpected not matched (%v)", req.Header)
}
}
}
39 changes: 35 additions & 4 deletions route.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,42 @@ func (r *Route) Schemes(schemes ...string) *Route {
// The above route will only match if both request header values match.
// If the value is an empty string, it will match any value if the key is set.
func (r *Route) Headers(pairs ...string) *Route {
if r.err == nil {
var headers map[string]comparison
headers, r.err = convertStringsToMapString(isEvenPairs, pairs...)
return r.addMatcher(headerMatcher(headers))
if r.err != nil {
return r
}

matcher, err := newHeaderMatcher(pairs...)

if err != nil {
r.err = err
}

r.addMatcher(matcher)

return r
}

// HeadersRegex adds a matcher for request header values.
// It accepts a sequence of key/value pairs to be matched. For example:
//
// r := mux.NewRouter()
// r.Headers("Content-Type", "application/(json|html)")
//
// The above route will only match if both request header values match.
// If the value is an empty string, it will match any value if the key is set.
func (r *Route) HeadersRegex(pairs ...string) *Route {
if r.err != nil {
return r
}

matcher, err := newHeaderRegexMatcher(pairs...)

if err != nil {
r.err = err
}

r.addMatcher(matcher)

return r
}

Expand Down

0 comments on commit 7f1c154

Please sign in to comment.