Optimizes tree lookup
This commit is contained in:
		
							
								
								
									
										29
									
								
								gin.go
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								gin.go
									
									
									
									
									
								
							@ -28,12 +28,12 @@ type (
 | 
			
		||||
	Engine struct {
 | 
			
		||||
		RouterGroup
 | 
			
		||||
		HTMLRender  render.HTMLRender
 | 
			
		||||
		pool        sync.Pool
 | 
			
		||||
		allNoRoute  HandlersChain
 | 
			
		||||
		allNoMethod HandlersChain
 | 
			
		||||
		noRoute     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
 | 
			
		||||
		// handler for the path with (without) the trailing slash exists.
 | 
			
		||||
@ -75,7 +75,7 @@ func New() *Engine {
 | 
			
		||||
		RedirectTrailingSlash:  true,
 | 
			
		||||
		RedirectFixedPath:      true,
 | 
			
		||||
		HandleMethodNotAllowed: true,
 | 
			
		||||
		trees: make(map[string]*node),
 | 
			
		||||
		trees: make(methodTrees, 0, 6),
 | 
			
		||||
	}
 | 
			
		||||
	engine.RouterGroup.engine = engine
 | 
			
		||||
	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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	root := engine.trees[method]
 | 
			
		||||
	root := engine.trees.get("method")
 | 
			
		||||
	if root == nil {
 | 
			
		||||
		root = new(node)
 | 
			
		||||
		engine.trees[method] = root
 | 
			
		||||
		engine.trees = append(engine.trees, methodTree{
 | 
			
		||||
			method: method,
 | 
			
		||||
			root:   root,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	root.addRoute(path, handlers)
 | 
			
		||||
}
 | 
			
		||||
@ -210,9 +213,11 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
 | 
			
		||||
	path := context.Request.URL.Path
 | 
			
		||||
 | 
			
		||||
	// Find root of the tree for the given HTTP method
 | 
			
		||||
	if root := engine.trees[httpMethod]; root != nil {
 | 
			
		||||
	t := engine.trees
 | 
			
		||||
	for i, tl := 0, len(t); i < tl; i++ {
 | 
			
		||||
		if t[i].method == httpMethod {
 | 
			
		||||
			// Find route in tree
 | 
			
		||||
		handlers, params, tsr := root.getValue(path, context.Params)
 | 
			
		||||
			handlers, params, tsr := t[i].root.getValue(path, context.Params)
 | 
			
		||||
			if handlers != nil {
 | 
			
		||||
				context.handlers = handlers
 | 
			
		||||
				context.Params = params
 | 
			
		||||
@ -221,16 +226,18 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
 | 
			
		||||
				return
 | 
			
		||||
 | 
			
		||||
			} else if httpMethod != "CONNECT" && path != "/" {
 | 
			
		||||
			if engine.serveAutoRedirect(context, root, tsr) {
 | 
			
		||||
				if engine.serveAutoRedirect(context, t[i].root, tsr) {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: unit test
 | 
			
		||||
	if engine.HandleMethodNotAllowed {
 | 
			
		||||
		for method, root := range engine.trees {
 | 
			
		||||
			if method != httpMethod {
 | 
			
		||||
				if handlers, _, _ := root.getValue(path, nil); handlers != nil {
 | 
			
		||||
		for _, tree := range engine.trees {
 | 
			
		||||
			if tree.method != httpMethod {
 | 
			
		||||
				if handlers, _, _ := tree.root.getValue(path, nil); handlers != nil {
 | 
			
		||||
					context.handlers = engine.allNoMethod
 | 
			
		||||
					serveError(context, 405, default405Body)
 | 
			
		||||
					return
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								tree.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								tree.go
									
									
									
									
									
								
							@ -36,6 +36,22 @@ func (ps Params) ByName(name string) (va string) {
 | 
			
		||||
	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 {
 | 
			
		||||
	if a <= b {
 | 
			
		||||
		return a
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user