Optimizes tree lookup
This commit is contained in:
parent
9584e4ea5c
commit
66e9feb622
47
gin.go
47
gin.go
@ -28,12 +28,12 @@ type (
|
|||||||
Engine struct {
|
Engine struct {
|
||||||
RouterGroup
|
RouterGroup
|
||||||
HTMLRender render.HTMLRender
|
HTMLRender render.HTMLRender
|
||||||
pool sync.Pool
|
|
||||||
allNoRoute HandlersChain
|
allNoRoute HandlersChain
|
||||||
allNoMethod HandlersChain
|
allNoMethod HandlersChain
|
||||||
noRoute HandlersChain
|
noRoute HandlersChain
|
||||||
noMethod HandlersChain
|
noMethod HandlersChain
|
||||||
trees map[string]*node
|
pool sync.Pool
|
||||||
|
trees methodTrees
|
||||||
|
|
||||||
// Enables automatic redirection if the current route can't be matched but a
|
// Enables automatic redirection if the current route can't be matched but a
|
||||||
// handler for the path with (without) the trailing slash exists.
|
// handler for the path with (without) the trailing slash exists.
|
||||||
@ -75,7 +75,7 @@ func New() *Engine {
|
|||||||
RedirectTrailingSlash: true,
|
RedirectTrailingSlash: true,
|
||||||
RedirectFixedPath: true,
|
RedirectFixedPath: true,
|
||||||
HandleMethodNotAllowed: true,
|
HandleMethodNotAllowed: true,
|
||||||
trees: make(map[string]*node),
|
trees: make(methodTrees, 0, 6),
|
||||||
}
|
}
|
||||||
engine.RouterGroup.engine = engine
|
engine.RouterGroup.engine = engine
|
||||||
engine.pool.New = func() interface{} {
|
engine.pool.New = func() interface{} {
|
||||||
@ -155,10 +155,13 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
|
|||||||
panic("there must be at least one handler")
|
panic("there must be at least one handler")
|
||||||
}
|
}
|
||||||
|
|
||||||
root := engine.trees[method]
|
root := engine.trees.get("method")
|
||||||
if root == nil {
|
if root == nil {
|
||||||
root = new(node)
|
root = new(node)
|
||||||
engine.trees[method] = root
|
engine.trees = append(engine.trees, methodTree{
|
||||||
|
method: method,
|
||||||
|
root: root,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
root.addRoute(path, handlers)
|
root.addRoute(path, handlers)
|
||||||
}
|
}
|
||||||
@ -210,27 +213,31 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
|
|||||||
path := context.Request.URL.Path
|
path := context.Request.URL.Path
|
||||||
|
|
||||||
// Find root of the tree for the given HTTP method
|
// Find root of the tree for the given HTTP method
|
||||||
if root := engine.trees[httpMethod]; root != nil {
|
t := engine.trees
|
||||||
// Find route in tree
|
for i, tl := 0, len(t); i < tl; i++ {
|
||||||
handlers, params, tsr := root.getValue(path, context.Params)
|
if t[i].method == httpMethod {
|
||||||
if handlers != nil {
|
// Find route in tree
|
||||||
context.handlers = handlers
|
handlers, params, tsr := t[i].root.getValue(path, context.Params)
|
||||||
context.Params = params
|
if handlers != nil {
|
||||||
context.Next()
|
context.handlers = handlers
|
||||||
context.writermem.WriteHeaderNow()
|
context.Params = params
|
||||||
return
|
context.Next()
|
||||||
|
context.writermem.WriteHeaderNow()
|
||||||
} else if httpMethod != "CONNECT" && path != "/" {
|
|
||||||
if engine.serveAutoRedirect(context, root, tsr) {
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
} else if httpMethod != "CONNECT" && path != "/" {
|
||||||
|
if engine.serveAutoRedirect(context, t[i].root, tsr) {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: unit test
|
||||||
if engine.HandleMethodNotAllowed {
|
if engine.HandleMethodNotAllowed {
|
||||||
for method, root := range engine.trees {
|
for _, tree := range engine.trees {
|
||||||
if method != httpMethod {
|
if tree.method != httpMethod {
|
||||||
if handlers, _, _ := root.getValue(path, nil); handlers != nil {
|
if handlers, _, _ := tree.root.getValue(path, nil); handlers != nil {
|
||||||
context.handlers = engine.allNoMethod
|
context.handlers = engine.allNoMethod
|
||||||
serveError(context, 405, default405Body)
|
serveError(context, 405, default405Body)
|
||||||
return
|
return
|
||||||
|
16
tree.go
16
tree.go
@ -36,6 +36,22 @@ func (ps Params) ByName(name string) (va string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type methodTree struct {
|
||||||
|
method string
|
||||||
|
root *node
|
||||||
|
}
|
||||||
|
|
||||||
|
type methodTrees []methodTree
|
||||||
|
|
||||||
|
func (trees methodTrees) get(method string) *node {
|
||||||
|
for _, tree := range trees {
|
||||||
|
if tree.method == method {
|
||||||
|
return tree.root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func min(a, b int) int {
|
func min(a, b int) int {
|
||||||
if a <= b {
|
if a <= b {
|
||||||
return a
|
return a
|
||||||
|
Loading…
Reference in New Issue
Block a user