Hold route full path in the Context

This commit is contained in:
Roman Zaynetdinov 2019-03-26 09:36:34 +02:00
parent 7d4cee14b5
commit 7d7c20808e
4 changed files with 60 additions and 0 deletions

View File

@ -48,6 +48,7 @@ type Context struct {
Params Params Params Params
handlers HandlersChain handlers HandlersChain
index int8 index int8
fullPath string
engine *Engine engine *Engine
@ -70,6 +71,7 @@ func (c *Context) reset() {
c.Params = c.Params[0:0] c.Params = c.Params[0:0]
c.handlers = nil c.handlers = nil
c.index = -1 c.index = -1
c.fullPath = ""
c.Keys = nil c.Keys = nil
c.Errors = c.Errors[0:0] c.Errors = c.Errors[0:0]
c.Accepted = nil c.Accepted = nil
@ -111,6 +113,15 @@ func (c *Context) Handler() HandlerFunc {
return c.handlers.Last() return c.handlers.Last()
} }
// FullPath returns a matched route full path. For not found routes
// returns an empty string.
// router.GET("/user/:id", func(c *gin.Context) {
// c.FullPath() == "/user/:id" // true
// })
func (c *Context) FullPath() string {
return c.fullPath
}
/************************************/ /************************************/
/*********** FLOW CONTROL ***********/ /*********** FLOW CONTROL ***********/
/************************************/ /************************************/

2
gin.go
View File

@ -252,6 +252,7 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
root := engine.trees.get(method) root := engine.trees.get(method)
if root == nil { if root == nil {
root = new(node) root = new(node)
root.fullPath = "/"
engine.trees = append(engine.trees, methodTree{method: method, root: root}) engine.trees = append(engine.trees, methodTree{method: method, root: root})
} }
root.addRoute(path, handlers) root.addRoute(path, handlers)
@ -385,6 +386,7 @@ func (engine *Engine) handleHTTPRequest(c *Context) {
if value.handlers != nil { if value.handlers != nil {
c.handlers = value.handlers c.handlers = value.handlers
c.Params = value.params c.Params = value.params
c.fullPath = value.fullPath
c.Next() c.Next()
c.writermem.WriteHeaderNow() c.writermem.WriteHeaderNow()
return return

View File

@ -522,3 +522,38 @@ func TestRouteServeErrorWithWriteHeader(t *testing.T) {
assert.Equal(t, 421, w.Code) assert.Equal(t, 421, w.Code)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
} }
func TestRouteContextHoldsFullPath(t *testing.T) {
router := New()
// Test routes
routes := []string{
"/",
"/simple",
"/project/:name",
"/project/:name/build/*params",
}
for _, route := range routes {
actualRoute := route
router.GET(route, func(c *Context) {
// For each defined route context should contain its full path
assert.Equal(t, actualRoute, c.FullPath())
c.AbortWithStatus(http.StatusOK)
})
}
for _, route := range routes {
w := performRequest(router, "GET", route)
assert.Equal(t, http.StatusOK, w.Code)
}
// Test not found
router.Use(func(c *Context) {
// For not found routes full path is empty
assert.Equal(t, "", c.FullPath())
})
w := performRequest(router, "GET", "/not-found")
assert.Equal(t, http.StatusNotFound, w.Code)
}

12
tree.go
View File

@ -94,6 +94,7 @@ type node struct {
nType nodeType nType nodeType
maxParams uint8 maxParams uint8
wildChild bool wildChild bool
fullPath string
} }
// increments priority of the given child and reorders if necessary. // increments priority of the given child and reorders if necessary.
@ -154,6 +155,7 @@ func (n *node) addRoute(path string, handlers HandlersChain) {
children: n.children, children: n.children,
handlers: n.handlers, handlers: n.handlers,
priority: n.priority - 1, priority: n.priority - 1,
fullPath: fullPath,
} }
// Update maxParams (max of all children) // Update maxParams (max of all children)
@ -229,6 +231,7 @@ func (n *node) addRoute(path string, handlers HandlersChain) {
n.indices += string([]byte{c}) n.indices += string([]byte{c})
child := &node{ child := &node{
maxParams: numParams, maxParams: numParams,
fullPath: fullPath,
} }
n.children = append(n.children, child) n.children = append(n.children, child)
n.incrementChildPrio(len(n.indices) - 1) n.incrementChildPrio(len(n.indices) - 1)
@ -296,6 +299,7 @@ func (n *node) insertChild(numParams uint8, path string, fullPath string, handle
child := &node{ child := &node{
nType: param, nType: param,
maxParams: numParams, maxParams: numParams,
fullPath: fullPath,
} }
n.children = []*node{child} n.children = []*node{child}
n.wildChild = true n.wildChild = true
@ -312,6 +316,7 @@ func (n *node) insertChild(numParams uint8, path string, fullPath string, handle
child := &node{ child := &node{
maxParams: numParams, maxParams: numParams,
priority: 1, priority: 1,
fullPath: fullPath,
} }
n.children = []*node{child} n.children = []*node{child}
n = child n = child
@ -339,6 +344,7 @@ func (n *node) insertChild(numParams uint8, path string, fullPath string, handle
wildChild: true, wildChild: true,
nType: catchAll, nType: catchAll,
maxParams: 1, maxParams: 1,
fullPath: fullPath,
} }
n.children = []*node{child} n.children = []*node{child}
n.indices = string(path[i]) n.indices = string(path[i])
@ -352,6 +358,7 @@ func (n *node) insertChild(numParams uint8, path string, fullPath string, handle
maxParams: 1, maxParams: 1,
handlers: handlers, handlers: handlers,
priority: 1, priority: 1,
fullPath: fullPath,
} }
n.children = []*node{child} n.children = []*node{child}
@ -364,10 +371,12 @@ func (n *node) insertChild(numParams uint8, path string, fullPath string, handle
n.handlers = handlers n.handlers = handlers
} }
// nodeValue holds return values of (*Node).getValue method
type nodeValue struct { type nodeValue struct {
handlers HandlersChain handlers HandlersChain
params Params params Params
tsr bool tsr bool
fullPath string
} }
// getValue returns the handle registered with the given path (key). The values of // getValue returns the handle registered with the given path (key). The values of
@ -442,6 +451,7 @@ walk: // Outer loop for walking the tree
} }
if value.handlers = n.handlers; value.handlers != nil { if value.handlers = n.handlers; value.handlers != nil {
value.fullPath = n.fullPath
return return
} }
if len(n.children) == 1 { if len(n.children) == 1 {
@ -471,6 +481,7 @@ walk: // Outer loop for walking the tree
} }
value.handlers = n.handlers value.handlers = n.handlers
value.fullPath = n.fullPath
return return
default: default:
@ -481,6 +492,7 @@ walk: // Outer loop for walking the tree
// We should have reached the node containing the handle. // We should have reached the node containing the handle.
// Check if this node has a handle registered. // Check if this node has a handle registered.
if value.handlers = n.handlers; value.handlers != nil { if value.handlers = n.handlers; value.handlers != nil {
value.fullPath = n.fullPath
return return
} }