Browse Source

Merge 38b9e10ecf into 91708ff8e3

pull/652/merge
Grégoire Duchêne 4 years ago committed by GitHub
parent
commit
53610881c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      mux.go
  2. 7
      mux_test.go
  3. 7
      route.go

19
mux.go

@ -11,6 +11,7 @@ import ( @@ -11,6 +11,7 @@ import (
"net/http"
"path"
"regexp"
"strings"
)
var (
@ -202,7 +203,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { @@ -202,7 +203,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
if handler == nil && match.MatchErr == ErrMethodMismatch {
handler = methodNotAllowedHandler()
handler = methodNotAllowedHandler(match.AllowedMethods)
}
if handler == nil {
@ -417,6 +418,10 @@ type RouteMatch struct { @@ -417,6 +418,10 @@ type RouteMatch struct {
// It is set to ErrMethodMismatch if there is a mismatch in
// the request method and route method
MatchErr error
// AllowedMethods contains the list of methods allowed by a route when
// MatchErr is set to ErrMethodMismatch.
AllowedMethods []string
}
type contextKey int
@ -598,11 +603,11 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s @@ -598,11 +603,11 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s
return true
}
// methodNotAllowed replies to the request with an HTTP status code 405.
func methodNotAllowed(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusMethodNotAllowed)
}
// methodNotAllowedHandler returns a simple request handler
// that replies to each request with a status code 405.
func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) }
func methodNotAllowedHandler(allowed []string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Allow", strings.Join(allowed, ","))
w.WriteHeader(http.StatusMethodNotAllowed)
})
}

7
mux_test.go

@ -2052,6 +2052,9 @@ func TestNoMatchMethodErrorHandler(t *testing.T) { @@ -2052,6 +2052,9 @@ func TestNoMatchMethodErrorHandler(t *testing.T) {
if resp.Code != http.StatusMethodNotAllowed {
t.Errorf("Expecting code %v", 405)
}
if hdr := resp.Header().Get("Allow"); hdr != "GET,POST" {
t.Errorf(`Expected Allow header to be "GET,POST" (got %q)`, hdr)
}
// Add matching route
r.HandleFunc("/", func1).Methods("PUT")
@ -2721,7 +2724,6 @@ func TestMethodNotAllowed(t *testing.T) { @@ -2721,7 +2724,6 @@ func TestMethodNotAllowed(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }
router := NewRouter()
router.HandleFunc("/thing", handler).Methods(http.MethodGet)
router.HandleFunc("/something", handler).Methods(http.MethodGet)
w := NewRecorder()
req := newRequest(http.MethodPut, "/thing")
@ -2731,6 +2733,9 @@ func TestMethodNotAllowed(t *testing.T) { @@ -2731,6 +2733,9 @@ func TestMethodNotAllowed(t *testing.T) {
if w.Code != http.StatusMethodNotAllowed {
t.Fatalf("Expected status code 405 (got %d)", w.Code)
}
if hdr := w.Header().Get("Allow"); hdr != http.MethodGet {
t.Fatalf(`Expected Allow header to be "GET" (got %q)`, hdr)
}
}
type customMethodNotAllowedHandler struct {

7
route.go

@ -44,12 +44,14 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { @@ -44,12 +44,14 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
}
var matchErr error
var allowedMethods []string
// Match everything.
for _, m := range r.matchers {
if matched := m.Match(req, match); !matched {
if _, ok := m.(methodMatcher); ok {
if m, ok := m.(methodMatcher); ok {
matchErr = ErrMethodMismatch
allowedMethods = m
continue
}
@ -71,6 +73,9 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { @@ -71,6 +73,9 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
if matchErr != nil {
match.MatchErr = matchErr
if matchErr == ErrMethodMismatch {
match.AllowedMethods = allowedMethods
}
return false
}

Loading…
Cancel
Save