129 lines
2.6 KiB
Go
129 lines
2.6 KiB
Go
package sux
|
|
|
|
import (
|
|
"net/http"
|
|
)
|
|
|
|
const (
|
|
nomatch uint8 = iota
|
|
static
|
|
)
|
|
|
|
type (
|
|
node struct {
|
|
term byte
|
|
ntype uint8
|
|
handler http.HandlerFunc
|
|
child []*node
|
|
}
|
|
Router struct {
|
|
route map[string]*node
|
|
}
|
|
)
|
|
|
|
var root *Router
|
|
|
|
func makenode(term byte) *node {
|
|
return &node{
|
|
term: term,
|
|
child: make([]*node, 0),
|
|
}
|
|
}
|
|
|
|
func (n *node) addchild(term byte) *node {
|
|
if fn := n.findchild(term); fn == nil {
|
|
nn := makenode(term)
|
|
n.child = append(n.child, nn)
|
|
return nn
|
|
} else {
|
|
return fn
|
|
}
|
|
}
|
|
|
|
func (n *node) maketree(word []byte, handler http.HandlerFunc) {
|
|
m := n
|
|
for i, l := 1, len(word); i < l; i++ {
|
|
m = m.addchild(word[i])
|
|
}
|
|
m.ntype = static
|
|
m.handler = handler
|
|
}
|
|
|
|
func (n *node) findchild(term byte) *node {
|
|
for _, v := range n.child {
|
|
if v.term == term {
|
|
return v
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (n *node) find(word string) *node {
|
|
ss := []byte(word)
|
|
m := n
|
|
for i, l := 1, len(ss); i < l; i++ {
|
|
m = m.findchild(ss[i])
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (n *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if m, exists := n.route[r.Method]; exists {
|
|
m = m.find(r.URL.Path)
|
|
if m == nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if m.ntype == nomatch {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
m.handler(w, r)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (n *Router) GET(path string, handler http.HandlerFunc) *Router {
|
|
n.route["GET"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
func (n *Router) POST(path string, handler http.HandlerFunc) *Router {
|
|
n.route["POST"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
func (n *Router) PUT(path string, handler http.HandlerFunc) *Router {
|
|
n.route["PUT"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
func (n *Router) PATCH(path string, handler http.HandlerFunc) *Router {
|
|
n.route["PATCH"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
func (n *Router) DELETE(path string, handler http.HandlerFunc) *Router {
|
|
n.route["DELETE"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
func (n *Router) OPTIONS(path string, handler http.HandlerFunc) *Router {
|
|
n.route["OPTIONS"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
func (n *Router) HEAD(path string, handler http.HandlerFunc) *Router {
|
|
n.route["HEAD"].maketree([]byte(path), handler)
|
|
return n
|
|
}
|
|
|
|
func New() *Router {
|
|
root = &Router{route: make(map[string]*node)}
|
|
root.route["GET"] = makenode([]byte("/")[0])
|
|
root.route["POST"] = makenode([]byte("/")[0])
|
|
root.route["PUT"] = makenode([]byte("/")[0])
|
|
root.route["PATCH"] = makenode([]byte("/")[0])
|
|
root.route["DELETE"] = makenode([]byte("/")[0])
|
|
root.route["OPTIONS"] = makenode([]byte("/")[0])
|
|
root.route["HEAD"] = makenode([]byte("/")[0])
|
|
return root
|
|
}
|