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 }