Router a good
This commit is contained in:
67
tree.go
Normal file
67
tree.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var Wildcard = "{}"
|
||||
var WildcardHeader = "__wildcard_value__"
|
||||
|
||||
type tree struct {
|
||||
next map[string]*tree
|
||||
handler http.HandlerFunc
|
||||
}
|
||||
|
||||
func newTree() *tree {
|
||||
return &tree{
|
||||
next: make(map[string]*tree),
|
||||
handler: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tree) Lookup(path string) http.HandlerFunc {
|
||||
if path == "/" || path == "" {
|
||||
return t.handler
|
||||
}
|
||||
key, following := nextPathSegment(path)
|
||||
if n, ok := t.next[key]; ok {
|
||||
return n.Lookup(following)
|
||||
} else if n, ok := t.next[Wildcard]; ok {
|
||||
foo := n.Lookup(following)
|
||||
if foo != nil {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Header.Add(WildcardHeader, key)
|
||||
foo(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tree) Insert(path string, foo http.HandlerFunc) error {
|
||||
if path == "/" {
|
||||
if t.handler != nil {
|
||||
return errors.New("occupied path")
|
||||
}
|
||||
t.handler = foo
|
||||
return nil
|
||||
}
|
||||
key, following := nextPathSegment(path)
|
||||
_, ok := t.next[key]
|
||||
if !ok {
|
||||
t.next[key] = newTree()
|
||||
}
|
||||
return t.next[key].Insert(following, foo)
|
||||
}
|
||||
|
||||
func nextPathSegment(p string) (string, string) {
|
||||
p = path.Clean("/" + p)
|
||||
i := strings.Index(p[1:], "/") + 1
|
||||
if i <= 0 {
|
||||
return p[1:], "/"
|
||||
}
|
||||
return p[1:i], p[i:]
|
||||
}
|
||||
Reference in New Issue
Block a user