Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"net/http/httptest"
"net/url"
"reflect"
"regexp"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -2009,6 +2010,66 @@ func testQueriesTemplates(t *testing.T, test routeTest) {
}
}

func TestGetHeaders(t *testing.T) {
r := NewRouter()
route := r.NewRoute().Path("/v1/conversations").Headers(
"Content-Type", "application/json",
"X-Requested-With", "XMLHttpRequest",
)
got, err := route.GetHeaders()
if err != nil {
t.Fatalf("GetHeaders: %v", err)
}
want := map[string]string{
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
}
if !reflect.DeepEqual(got, want) {
t.Fatalf("GetHeaders = %#v, want %#v", got, want)
}

if _, err := r.NewRoute().Path("/no-headers").GetHeaders(); err == nil {
t.Fatal("GetHeaders: expected error for route without headers")
}

if _, err := r.NewRoute().Path("/regexp-only").HeadersRegexp("Accept", "html").GetHeaders(); err == nil {
t.Fatal("GetHeaders: expected error for HeadersRegexp-only route")
}
}

func TestGetHeadersRegexp(t *testing.T) {
r := NewRouter()
route := r.NewRoute().Path("/v1").HeadersRegexp(
"Content-Type", "application/(text|json)",
"X-Requested-With", "XMLHttpRequest",
)
got, err := route.GetHeadersRegexp()
if err != nil {
t.Fatalf("GetHeadersRegexp: %v", err)
}
if len(got) != 2 {
t.Fatalf("GetHeadersRegexp len = %d, want 2: %#v", len(got), got)
}
re, err := regexp.Compile(got["Content-Type"])
if err != nil {
t.Fatalf("GetHeadersRegexp Content-Type: %v", err)
}
if !re.MatchString("application/json") || re.MatchString("application/xml") {
t.Fatalf("GetHeadersRegexp Content-Type %q did not match as registered", got["Content-Type"])
}
if got["X-Requested-With"] == "" {
t.Fatalf("GetHeadersRegexp missing X-Requested-With: %#v", got)
}

if _, err := r.NewRoute().Path("/no-headers").GetHeadersRegexp(); err == nil {
t.Fatal("GetHeadersRegexp: expected error for route without header regexps")
}

if _, err := r.NewRoute().Path("/exact-only").Headers("Accept", "text/html").GetHeadersRegexp(); err == nil {
t.Fatal("GetHeadersRegexp: expected error for Headers-only route")
}
}

type TestA301ResponseWriter struct {
hh http.Header
status int
Expand Down
48 changes: 48 additions & 0 deletions route.go
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,54 @@ func (r *Route) GetMethods() ([]string, error) {
return nil, errors.New("mux: route doesn't have methods")
}

// GetHeaders returns the exact header name/value pairs the route matches against.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
// An error will be returned if the route does not have headers.
func (r *Route) GetHeaders() (map[string]string, error) {
if r.err != nil {
return nil, r.err
}
out := make(map[string]string)
found := false
for _, m := range r.matchers {
if headers, ok := m.(headerMatcher); ok {
found = true
for k, v := range headers {
out[k] = v
}
}
}
if !found {
return nil, errors.New("mux: route doesn't have headers")
}
return out, nil
}

// GetHeadersRegexp returns the header name/regexp pairs the route matches against.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
// An error will be returned if the route does not have header regular expressions.
func (r *Route) GetHeadersRegexp() (map[string]string, error) {
if r.err != nil {
return nil, r.err
}
out := make(map[string]string)
found := false
for _, m := range r.matchers {
if headers, ok := m.(headerRegexMatcher); ok {
found = true
for k, v := range headers {
out[k] = v.String()
}
}
}
if !found {
return nil, errors.New("mux: route doesn't have header regexps")
}
return out, nil
}

// GetHostTemplate returns the template used to build the
// route match.
// This is useful for building simple REST API documentation and for instrumentation
Expand Down
Loading