get and add methods get rewritten in an iterative manner instead of recursive.
This commit is contained in:
parent
538f1bd676
commit
89c2333a4f
132
httpr.go
132
httpr.go
@ -41,83 +41,93 @@ type node struct {
|
|||||||
handler http.HandlerFunc
|
handler http.HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) get(path path, idx int) (http.HandlerFunc, Params) {
|
func (n *node) get(path path) (http.HandlerFunc, Params) {
|
||||||
// Check if this node is a catch-all endpoint.
|
pathLen := len(path)
|
||||||
if n.endpoint[0] == '*' {
|
curNode := n
|
||||||
var p Params = Params{}
|
|
||||||
p[n.endpoint[1:]] = strings.Join(path[idx:], "/")
|
|
||||||
return n.handler, p
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this endpoint is a parameter, then add its name to a path's part.
|
outer:
|
||||||
// This will be used further to fill Params.
|
for i := range path {
|
||||||
if n.endpoint[0] == ':' {
|
// Check if this node is a catch-all endpoint.
|
||||||
path[idx] = n.endpoint + ":" + path[idx]
|
if curNode.endpoint[0] == '*' {
|
||||||
}
|
var p Params = Params{}
|
||||||
|
p[curNode.endpoint[1:]] = strings.Join(path[i:], "/")
|
||||||
if len(path) == idx+1 {
|
return curNode.handler, p
|
||||||
var params Params = make(Params)
|
|
||||||
|
|
||||||
for _, part := range path {
|
|
||||||
if part[0] == ':' {
|
|
||||||
param := strings.Split(part[1:], ":")
|
|
||||||
params[param[0]] = param[1]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n.handler, params
|
// If this is a parametrised endpoint, then add its name to
|
||||||
}
|
// a path's part. It will be used further to parse parameters.
|
||||||
|
if curNode.endpoint[0] == ':' {
|
||||||
if len(path) > idx+1 {
|
path[i] = curNode.endpoint + ":" + path[i]
|
||||||
var wildcardOrParam *node
|
|
||||||
for _, next := range n.children {
|
|
||||||
if next.endpoint == path[idx+1] {
|
|
||||||
return next.get(path, idx+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if next.endpoint[0] == ':' || next.endpoint[0] == '*' {
|
|
||||||
wildcardOrParam = next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if wildcardOrParam != nil {
|
if pathLen == i+1 {
|
||||||
return wildcardOrParam.get(path, idx+1)
|
var params Params = make(Params)
|
||||||
|
|
||||||
|
for _, part := range path {
|
||||||
|
if part[0] == ':' {
|
||||||
|
param := strings.Split(part[1:], ":")
|
||||||
|
params[param[0]] = param[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.handler, params
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathLen > i+1 {
|
||||||
|
var paramNode *node
|
||||||
|
for _, next := range n.children {
|
||||||
|
if next.endpoint == path[i+1] {
|
||||||
|
curNode = next
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
|
||||||
|
if next.endpoint[0] == ':' || next.endpoint[0] == '*' {
|
||||||
|
paramNode = next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if paramNode != nil {
|
||||||
|
curNode = paramNode
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) add(path path, idx int, handler http.HandlerFunc) error {
|
func (n *node) add(path path, handler http.HandlerFunc) error {
|
||||||
// If it is a last part of path, then set a handler to this node.
|
pathLen := len(path)
|
||||||
if len(path) == idx+1 {
|
curNode := n
|
||||||
n.endpoint = path[idx]
|
|
||||||
n.handler = handler
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if next part is a parameter and if it is, then look for
|
outer:
|
||||||
// an already existing endpoint with a different key.
|
for i := range path {
|
||||||
if path[idx+1][0] == '*' || path[idx+1][0] == ':' {
|
if pathLen == i+1 {
|
||||||
for _, child := range n.children {
|
if curNode.handler != nil {
|
||||||
if (child.endpoint[0] == '*' || child.endpoint[0] == ':') && path[idx+1] != child.endpoint {
|
return errors.New("attempt to redefine a handler for already existing path")
|
||||||
return errors.New("there is already a catch-all or regular param in there! You cannot add a second one")
|
|
||||||
}
|
}
|
||||||
}
|
curNode.endpoint = path[i]
|
||||||
}
|
curNode.handler = handler
|
||||||
|
|
||||||
// Check for an already existing endpoint.
|
|
||||||
for _, child := range n.children {
|
|
||||||
if child.endpoint == path[idx+1] {
|
|
||||||
child.add(path, idx+1, handler)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// No endpoint was found.
|
for _, child := range n.children {
|
||||||
new_child := &node{endpoint: path[idx+1]}
|
firstChar := path[i+1][0]
|
||||||
new_child.add(path, idx+1, handler)
|
if (firstChar == ':' || firstChar == '*') && firstChar == child.endpoint[0] {
|
||||||
n.children = append(n.children, new_child)
|
curNode = child
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
|
||||||
|
if child.endpoint == path[i+1] {
|
||||||
|
curNode = child
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newChild := &node{endpoint: path[i+1]}
|
||||||
|
curNode.children = append(curNode.children, newChild)
|
||||||
|
curNode = newChild
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user