@@ -13,6 +13,10 @@ import (
13
13
"strings"
14
14
)
15
15
16
+ var (
17
+ ErrMethodMismatch = errors .New ("method is not allowed" )
18
+ )
19
+
16
20
// NewRouter returns a new router instance.
17
21
func NewRouter () * Router {
18
22
return & Router {namedRoutes : make (map [string ]* Route ), KeepContext : false }
@@ -39,6 +43,10 @@ func NewRouter() *Router {
39
43
type Router struct {
40
44
// Configurable Handler to be used when no route matches.
41
45
NotFoundHandler http.Handler
46
+
47
+ // Configurable Handler to be used when the request method does not match the route.
48
+ MethodNotAllowedHandler http.Handler
49
+
42
50
// Parent route, if this is a subrouter.
43
51
parent parentRoute
44
52
// Routes to be matched, in order.
@@ -65,6 +73,11 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
65
73
}
66
74
}
67
75
76
+ if match .MatchErr == ErrMethodMismatch && r .MethodNotAllowedHandler != nil {
77
+ match .Handler = r .MethodNotAllowedHandler
78
+ return true
79
+ }
80
+
68
81
// Closest match for a router (includes sub-routers)
69
82
if r .NotFoundHandler != nil {
70
83
match .Handler = r .NotFoundHandler
@@ -105,9 +118,15 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
105
118
req = setVars (req , match .Vars )
106
119
req = setCurrentRoute (req , match .Route )
107
120
}
121
+
122
+ if handler == nil && match .MatchErr == ErrMethodMismatch {
123
+ handler = methodNotAllowedHandler ()
124
+ }
125
+
108
126
if handler == nil {
109
127
handler = http .NotFoundHandler ()
110
128
}
129
+
111
130
if ! r .KeepContext {
112
131
defer contextClear (req )
113
132
}
@@ -344,6 +363,11 @@ type RouteMatch struct {
344
363
Route * Route
345
364
Handler http.Handler
346
365
Vars map [string ]string
366
+
367
+ // MatchErr is set to appropriate matching error
368
+ // It is set to ErrMethodMismatch if there is a mismatch in
369
+ // the request method and route method
370
+ MatchErr error
347
371
}
348
372
349
373
type contextKey int
@@ -545,3 +569,12 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s
545
569
}
546
570
return true
547
571
}
572
+
573
+ // methodNotAllowed replies to the request with an HTTP status code 405.
574
+ func methodNotAllowed (w http.ResponseWriter , r * http.Request ) {
575
+ w .WriteHeader (http .StatusMethodNotAllowed )
576
+ }
577
+
578
+ // methodNotAllowedHandler returns a simple request handler
579
+ // that replies to each request with a status code 405.
580
+ func methodNotAllowedHandler () http.Handler { return http .HandlerFunc (methodNotAllowed ) }
0 commit comments