1
0
mirror of https://github.com/labstack/echo.git synced 2025-03-23 21:29:26 +02:00
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2015-04-26 12:44:38 -07:00
parent 0a075ce7c5
commit 67b1dfea04
2 changed files with 65 additions and 28 deletions

View File

@ -13,11 +13,11 @@ type (
prefix string prefix string
parent *node parent *node
children children children children
// pchild *node // Param child pchild *node // Param child
// cchild *node // Catch-all child cchild *node // Catch-all child
handler HandlerFunc handler HandlerFunc
pnames []string pnames []string
echo *Echo echo *Echo
} }
ntype uint8 ntype uint8
children []*node children []*node
@ -96,11 +96,18 @@ func (r *router) insert(method, path string, h HandlerFunc, t ntype, pnames []st
// Split node // Split node
n := newNode(t, cn.prefix[l:], cn, cn.children, cn.handler, cn.pnames, cn.echo) n := newNode(t, cn.prefix[l:], cn, cn.children, cn.handler, cn.pnames, cn.echo)
cn.children = children{n} // Add to parent cn.children = children{n} // Add to parent
// if n.typ == ptype {
// cn.pchild = n
// } else if n.typ == ctype {
// cn.cchild = n
// }
// Reset parent node // Reset parent node
cn.typ = stype cn.typ = stype
cn.label = cn.prefix[0] cn.label = cn.prefix[0]
cn.prefix = cn.prefix[:l] cn.prefix = cn.prefix[:l]
// cn.pchild = nil
// cn.cchild = nil
cn.handler = nil cn.handler = nil
cn.pnames = nil cn.pnames = nil
cn.echo = nil cn.echo = nil
@ -115,6 +122,11 @@ func (r *router) insert(method, path string, h HandlerFunc, t ntype, pnames []st
// Create child node // Create child node
n = newNode(t, search[l:], cn, children{}, h, pnames, echo) n = newNode(t, search[l:], cn, children{}, h, pnames, echo)
cn.children = append(cn.children, n) cn.children = append(cn.children, n)
// if n.typ == ptype {
// cn.pchild = n
// } else if n.typ == ctype {
// cn.cchild = n
// }
} }
} else if l < sl { } else if l < sl {
search = search[l:] search = search[l:]
@ -127,6 +139,11 @@ func (r *router) insert(method, path string, h HandlerFunc, t ntype, pnames []st
// Create child node // Create child node
n := newNode(t, search, cn, children{}, h, pnames, echo) n := newNode(t, search, cn, children{}, h, pnames, echo)
cn.children = append(cn.children, n) cn.children = append(cn.children, n)
// if n.typ == ptype {
// cn.pchild = n
// } else if n.typ == ctype {
// cn.cchild = n
// }
} else { } else {
// Node already exists // Node already exists
if h != nil { if h != nil {
@ -139,8 +156,8 @@ func (r *router) insert(method, path string, h HandlerFunc, t ntype, pnames []st
} }
} }
func newNode(t ntype, pfx string, p *node, c children, h HandlerFunc, pnames []string, echo *Echo) (n *node) { func newNode(t ntype, pfx string, p *node, c children, h HandlerFunc, pnames []string, echo *Echo) *node {
n = &node{ return &node{
typ: t, typ: t,
label: pfx[0], label: pfx[0],
prefix: pfx, prefix: pfx,
@ -150,7 +167,9 @@ func newNode(t ntype, pfx string, p *node, c children, h HandlerFunc, pnames []s
pnames: pnames, pnames: pnames,
echo: echo, echo: echo,
} }
return }
func (n *node) addChild(c *node) {
} }
func (n *node) findChild(l byte) *node { func (n *node) findChild(l byte) *node {
@ -201,20 +220,22 @@ func lcp(a, b string) (i int) {
return return
} }
func (r *router) Find(method, path string, c *Context) (h HandlerFunc, echo *Echo) { func (r *router) Find(method, path string, ctx *Context) (h HandlerFunc, echo *Echo) {
cn := r.trees[method] // Current node as root cn := r.trees[method] // Current node as root
search := path search := path
chn := new(node) // Child node c := new(node) // Child node
n := 0 // Param counter n := 0 // Param counter
// Search order static > param > catch-all // Search order static > param > catch-all
for { for {
if search == "" || search == cn.prefix { if search == "" || search == cn.prefix {
// Found if cn.handler != nil {
h = cn.handler // Found
c.pnames = cn.pnames h = cn.handler
echo = cn.echo ctx.pnames = cn.pnames
return echo = cn.echo
return
}
} }
pl := len(cn.prefix) pl := len(cn.prefix)
@ -226,32 +247,40 @@ func (r *router) Find(method, path string, c *Context) (h HandlerFunc, echo *Ech
goto Up goto Up
} }
// Check for catch-all with empty string
if len(search) == 0 {
goto CatchAll
}
// Static node // Static node
chn = cn.findSchild(search[0]) c = cn.findSchild(search[0])
if chn != nil { if c != nil {
cn = chn cn = c
continue continue
} }
// Param node // Param node
Param: Param:
chn = cn.findPchild() c = cn.findPchild()
if chn != nil { // c = cn.pchild
cn = chn if c != nil {
cn = c
i, l := 0, len(search) i, l := 0, len(search)
for ; i < l && search[i] != '/'; i++ { for ; i < l && search[i] != '/'; i++ {
} }
c.pvalues[n] = search[:i] ctx.pvalues[n] = search[:i]
n++ n++
search = search[i:] search = search[i:]
continue continue
} }
// Catch-all node // Catch-all node
chn = cn.findCchild() CatchAll:
if chn != nil { // c = cn.cchild
cn = chn c = cn.findCchild()
c.pvalues[n] = search if c != nil {
cn = c
ctx.pvalues[n] = search
search = "" // End search search = "" // End search
continue continue
} }

View File

@ -344,7 +344,15 @@ func TestRouterCatchAll(t *testing.T) {
return nil return nil
}, nil) }, nil)
h, _ := r.Find(GET, "/users/joe", context) h, _ := r.Find(GET, "/users/", context)
if h == nil {
t.Fatal("handler not found")
}
if context.pvalues[0] != "" {
t.Error("value should be joe")
}
h, _ = r.Find(GET, "/users/joe", context)
if h == nil { if h == nil {
t.Fatal("handler not found") t.Fatal("handler not found")
} }