// FilterParam adds the middleware filter iff the URL parameter exists. func (r *Router) FilterParam(param string, filter http.HandlerFunc) { r.Filter(func(w http.ResponseWriter, req *http.Request) { c := context.Get(req) if len(c.Params.Get(param)) > 0 { filter(w, req) } }) }
// Required by http.Handler interface. This method is invoked by the // http server and will handle all page routing func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) { r.RLock() defer r.RUnlock() //wrap the response writer in our custom interface w := &responseWriter{writer: rw, Router: r} //find a matching Route for _, route := range r.routes { //if the methods don't match, skip this handler //i.e if request.Method is 'PUT' Route.Method must be 'PUT' if req.Method != route.method { continue } //check if Route pattern matches url if !route.regex.MatchString(req.URL.Path) { continue } //get submatches (params) matches := route.regex.FindStringSubmatch(req.URL.Path) //double check that the Route matches the URL pattern. if len(matches[0]) != len(req.URL.Path) { continue } //create the http.Requests context c := context.Get(req) //add url parameters to the context for i, match := range matches[1:] { c.Params.Set(route.params[i], match) } //execute middleware filters for _, filter := range r.filters { filter(w, req) if w.started { return } } //invoke the request handler route.handler(w, req) return } //if no matches to url, throw a not found exception if w.started == false { http.NotFound(w, req) } }
// TestFilter tests that a route is filtered prior to handling func TestRouteFilter(t *testing.T) { r, _ := http.NewRequest("GET", "/person/anderson/thomas?learn=kungfu", nil) w := httptest.NewRecorder() mux := New() mux.Filter(HandlerSetVar) mux.Get("/person/:last/:first", HandlerOk) mux.ServeHTTP(w, r) c := context.Get(r) password := c.Values.Get("password") if password != "z1on" { t.Errorf("session variable set to [%s]; want [%s]", password, "z1on") } if w.Body.String() != "hello world" { t.Errorf("Body set to [%s]; want [%s]", w.Body.String(), "hello world") } }
// TestRouteOk tests that the route is correctly handled, and the URL parameters // are added to the Context. func TestRouteOk(t *testing.T) { r, _ := http.NewRequest("GET", "/person/anderson/thomas?learn=kungfu", nil) w := httptest.NewRecorder() mux := New() mux.Get("/person/:last/:first", HandlerOk) mux.ServeHTTP(w, r) c := context.Get(r) lastNameParam := c.Params.Get("last") firstNameParam := c.Params.Get("first") if lastNameParam != "anderson" { t.Errorf("url param set to [%s]; want [%s]", lastNameParam, "anderson") } if firstNameParam != "thomas" { t.Errorf("url param set to [%s]; want [%s]", firstNameParam, "thomas") } if w.Body.String() != "hello world" { t.Errorf("Body set to [%s]; want [%s]", w.Body.String(), "hello world") } }
func HandlerSetVar(w http.ResponseWriter, r *http.Request) { c := context.Get(r) c.Values.Set("password", "z1on") }