33// license that can be found in the LICENSE file.
44
55/*
6- Package router 0.1.1 provides fast HTTP request router.
6+ Package router 0.2.0 provides fast HTTP request router.
77
88The router matches incoming requests by the request method and the path.
99If a handle is registered for this path and method, the router delegates the
@@ -71,15 +71,26 @@ package router
7171import (
7272 "log"
7373 "net/http"
74+ "strings"
7475)
7576
7677// Router represents a multiplexer for HTTP requests.
7778type Router struct {
79+ // List of handlers which accociated with known http methods (GET, POST ...)
7880 handlers map [string ]* parser
81+
7982 // NotFound is called when unknown HTTP method or a handler not found.
8083 // If it is not set, http.NotFound is used.
8184 // Please overwrite this if need your own NotFound handler.
8285 NotFound http.HandlerFunc
86+
87+ // PanicHandler is called when panic happen.
88+ // The handler prevents your server from crashing and should be used to return
89+ // http status code http.StatusInternalServerError (500)
90+ PanicHandler func (c * Control )
91+
92+ // Logger activates logging for each requests
93+ Logger bool
8394}
8495
8596// Handle type is aliased to type of handler function.
@@ -158,6 +169,19 @@ func (r *Router) Listen(hostPort string) {
158169
159170// ServeHTTP implements http.Handler interface.
160171func (r * Router ) ServeHTTP (w http.ResponseWriter , req * http.Request ) {
172+ defer func () {
173+ if recovery := recover (); recovery != nil {
174+ c := & Control {Request : req , Writer : w }
175+ if r .PanicHandler != nil {
176+ r .PanicHandler (c )
177+ } else {
178+ log .Println ("Recovered in handler:" , req .Method , req .URL .Path )
179+ }
180+ }
181+ }()
182+ if r .Logger {
183+ log .Println (req .Method , req .URL .Path )
184+ }
161185 if handle , params , ok := r .handlers [req .Method ].get (req .URL .Path ); ok {
162186 c := & Control {Request : req , Writer : w }
163187 if len (params ) > 0 {
@@ -166,11 +190,22 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
166190 handle (c )
167191 return
168192 }
193+ allowed := make ([]string , 0 , len (r .handlers ))
194+ for method , parser := range r .handlers {
195+ if _ , _ , ok := parser .get (req .URL .Path ); ok {
196+ allowed = append (allowed , method )
197+ }
198+ }
169199
170- if r .NotFound != nil {
171- r .NotFound (w , req )
172- } else {
173- http .NotFound (w , req )
200+ if len (allowed ) == 0 {
201+ if r .NotFound != nil {
202+ r .NotFound (w , req )
203+ } else {
204+ http .NotFound (w , req )
205+ }
206+ return
174207 }
175- return
208+
209+ w .Header ().Add ("Allow" , strings .Join (allowed , ", " ))
210+ http .Error (w , "Method Not Allowed" , http .StatusMethodNotAllowed )
176211}
0 commit comments