diff --git a/web/pattern.go b/web/pattern.go index 69f5654..903f6fd 100644 --- a/web/pattern.go +++ b/web/pattern.go @@ -19,7 +19,14 @@ type regexpPattern struct { func (p regexpPattern) Prefix() string { return p.prefix } -func (p regexpPattern) Match(r *http.Request, c *C, dryrun bool) bool { +func (p regexpPattern) Match(r *http.Request, c *C) bool { + return p.match(r, c, false) +} +func (p regexpPattern) Run(r *http.Request, c *C) { + p.match(r, c, false) +} + +func (p regexpPattern) match(r *http.Request, c *C, dryrun bool) bool { matches := p.re.FindStringSubmatch(r.URL.Path) if matches == nil || len(matches) == 0 { return false @@ -148,8 +155,13 @@ type stringPattern struct { func (s stringPattern) Prefix() string { return s.literals[0] } - -func (s stringPattern) Match(r *http.Request, c *C, dryrun bool) bool { +func (s stringPattern) Match(r *http.Request, c *C) bool { + return s.match(r, c, true) +} +func (s stringPattern) Run(r *http.Request, c *C) { + s.match(r, c, false) +} +func (s stringPattern) match(r *http.Request, c *C, dryrun bool) bool { path := r.URL.Path var matches map[string]string if !dryrun && len(s.pats) > 0 { diff --git a/web/pattern_test.go b/web/pattern_test.go index 2ea3c90..6b2575f 100644 --- a/web/pattern_test.go +++ b/web/pattern_test.go @@ -162,12 +162,13 @@ func TestPatterns(t *testing.T) { } func runTest(t *testing.T, p Pattern, test patternTest) { - result := p.Match(test.r, test.c, false) + result := p.Match(test.r, test.c) if result != test.match { t.Errorf("Expected match(%v, %#v) to return %v", p, test.r.URL.Path, test.match) return } + p.Run(test.r, test.c) if !reflect.DeepEqual(test.c, test.cout) { t.Errorf("Expected a context of %v, instead got %v", test.cout, diff --git a/web/router.go b/web/router.go index e5ed9dd..5c3c041 100644 --- a/web/router.go +++ b/web/router.go @@ -78,10 +78,13 @@ type Pattern interface { Prefix() string // Returns true if the request satisfies the pattern. This function is // free to examine both the request and the context to make this - // decision. After it is certain that the request matches, this function - // should mutate or create c.URLParams if necessary, unless dryrun is - // set. - Match(r *http.Request, c *C, dryrun bool) bool + // decision. Match should not modify either argument, and since it will + // potentially be called several times over the course of matching a + // request, it should be reasonably efficient. + Match(r *http.Request, c *C) bool + // Run the pattern on the request and context, modifying the context as + // necessary to bind URL parameters or other parsed state. + Run(r *http.Request, c *C) } func parsePattern(p interface{}) Pattern { @@ -144,13 +147,14 @@ type routeMachine struct { } func matchRoute(route route, m method, ms *method, r *http.Request, c *C) bool { - if !route.pattern.Match(r, c, true) { + if !route.pattern.Match(r, c) { return false } *ms |= route.method if route.method&m != 0 { - return route.pattern.Match(r, c, false) + route.pattern.Run(r, c) + return true } return false } diff --git a/web/router_test.go b/web/router_test.go index 442903e..59955cb 100644 --- a/web/router_test.go +++ b/web/router_test.go @@ -64,9 +64,11 @@ func (t testPattern) Prefix() string { return "" } -func (t testPattern) Match(r *http.Request, c *C, dryrun bool) bool { +func (t testPattern) Match(r *http.Request, c *C) bool { return true } +func (t testPattern) Run(r *http.Request, c *C) { +} var _ Pattern = testPattern{} @@ -174,9 +176,11 @@ type rsPattern struct { func (rs rsPattern) Prefix() string { return rs.prefix } -func (rs rsPattern) Match(_ *http.Request, _ *C, _ bool) bool { +func (rs rsPattern) Match(_ *http.Request, _ *C) bool { return rs.i >= *rs.counter } +func (rs rsPattern) Run(_ *http.Request, _ *C) { +} func (rs rsPattern) ServeHTTP(_ http.ResponseWriter, _ *http.Request) { rs.ichan <- rs.i