Browse Source

Split Pattern.Match in two; get rid of dryrun

The "dryrun" parameter on Pattern.Match was kind of ugly and made for an
exceedingly mediocre public interface. Instead, split its functionality
in two: the previous "dryrun" behavior now lives in the Match method,
and Patterns now actually mutate state when Run is called.

The code on the backend is of course still the same (for now), but at
least the interface is a little nicer.
Carl Jackson 12 years ago
parent
commit
e16aa3c10c
4 changed files with 33 additions and 12 deletions
  1. +15
    -3
      web/pattern.go
  2. +2
    -1
      web/pattern_test.go
  3. +10
    -6
      web/router.go
  4. +6
    -2
      web/router_test.go

+ 15
- 3
web/pattern.go View File

@ -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 {


+ 2
- 1
web/pattern_test.go View File

@ -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,


+ 10
- 6
web/router.go View File

@ -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
}


+ 6
- 2
web/router_test.go View File

@ -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


Loading…
Cancel
Save