diff --git a/_examples/custom-handler/main.go b/_examples/custom-handler/main.go new file mode 100644 index 00000000..3570d540 --- /dev/null +++ b/_examples/custom-handler/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "errors" + "net/http" + + "github.com/pressly/chi" +) + +type Handler func(w http.ResponseWriter, r *http.Request) error + +func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if err := h(w, r); err != nil { + // handle returned error here. + w.WriteHeader(503) + w.Write([]byte("bad")) + } +} + +func main() { + r := chi.NewRouter() + r.Method("GET", "/", Handler(fooHandler)) + http.ListenAndServe(":3333", r) +} + +func fooHandler(w http.ResponseWriter, r *http.Request) error { + q := r.URL.Query().Get("err") + + if q != "" { + return errors.New(q) + } + + w.Write([]byte("foo")) + return nil +} diff --git a/chi.go b/chi.go index e205acf0..1abb1d27 100644 --- a/chi.go +++ b/chi.go @@ -63,13 +63,10 @@ type Router interface { Handle(pattern string, h http.Handler) HandleFunc(pattern string, h http.HandlerFunc) - // TODO: support user-defined http method by string - // Handle(method, pattern string, h http.Handler) - // HandleFunc(method, pattern string, h http.HandlerFunc) - - // TODO: considering having a catch-all http method route - // like how Handle() currently behaves in chi v2 - // Any(pattern string, h http.HandlerFunc) + // Method and MethodFunc adds routes for `pattern` that matches + // the `method` HTTP method. + Method(method, pattern string, h http.Handler) + MethodFunc(method, pattern string, h http.HandlerFunc) // HTTP-method routing along `pattern` Connect(pattern string, h http.HandlerFunc) diff --git a/mux.go b/mux.go index af025e17..e6915ee5 100644 --- a/mux.go +++ b/mux.go @@ -106,6 +106,22 @@ func (mx *Mux) HandleFunc(pattern string, handlerFn http.HandlerFunc) { mx.handle(mALL, pattern, handlerFn) } +// Method adds the route `pattern` that matches `method` http method to +// execute the `handler` http.Handler. +func (mx *Mux) Method(method, pattern string, handler http.Handler) { + m, ok := methodMap[strings.ToUpper(method)] + if !ok { + panic(fmt.Sprintf("chi: '%s' http method is not supported.", method)) + } + mx.handle(m, pattern, handler) +} + +// MethodFunc adds the route `pattern` that matches `method` http method to +// execute the `handlerFn` http.HandlerFunc. +func (mx *Mux) MethodFunc(method, pattern string, handlerFn http.HandlerFunc) { + mx.Method(method, pattern, handlerFn) +} + // Connect adds the route `pattern` that matches a CONNECT http method to // execute the `handlerFn` http.HandlerFunc. func (mx *Mux) Connect(pattern string, handlerFn http.HandlerFunc) { diff --git a/mux_test.go b/mux_test.go index 277a0208..03a9ffff 100644 --- a/mux_test.go +++ b/mux_test.go @@ -111,9 +111,9 @@ func TestMuxBasic(t *testing.T) { m.Use(exmw) m.Use(logmw) m.Get("/", cxindex) - m.Get("/ping", ping) - m.Get("/pingall", pingAll) - m.Get("/ping/all", pingAll) + m.Method("GET", "/ping", http.HandlerFunc(ping)) + m.MethodFunc("GET", "/pingall", pingAll) + m.MethodFunc("get", "/ping/all", pingAll) m.Get("/ping/all2", pingAll2) m.Head("/ping", headPing)