mirror of https://github.com/gin-gonic/gin.git
Fix: 404 bug with param
This commit is contained in:
parent
1c48977cca
commit
cee994f045
|
@ -463,6 +463,8 @@ func TestTreeRunDynamicRouting(t *testing.T) {
|
||||||
testRequest(t, ts.URL+"/a/cc", "", "/:cc/cc")
|
testRequest(t, ts.URL+"/a/cc", "", "/:cc/cc")
|
||||||
testRequest(t, ts.URL+"/c1/d/e", "", "/c1/:dd/e")
|
testRequest(t, ts.URL+"/c1/d/e", "", "/c1/:dd/e")
|
||||||
testRequest(t, ts.URL+"/c1/d/e1", "", "/c1/:dd/e1")
|
testRequest(t, ts.URL+"/c1/d/e1", "", "/c1/:dd/e1")
|
||||||
|
testRequest(t, ts.URL+"/c1/dd/ee", "", "/:cc/:dd/ee")
|
||||||
|
testRequest(t, ts.URL+"/c1/dd/ee/", "", "/:cc/:dd/ee")
|
||||||
testRequest(t, ts.URL+"/c1/d/ee", "", "/:cc/:dd/ee")
|
testRequest(t, ts.URL+"/c1/d/ee", "", "/:cc/:dd/ee")
|
||||||
testRequest(t, ts.URL+"/c1/d/f", "", "/:cc/:dd/f")
|
testRequest(t, ts.URL+"/c1/d/f", "", "/:cc/:dd/f")
|
||||||
testRequest(t, ts.URL+"/c/d/ee", "", "/:cc/:dd/ee")
|
testRequest(t, ts.URL+"/c/d/ee", "", "/:cc/:dd/ee")
|
||||||
|
@ -480,6 +482,7 @@ func TestTreeRunDynamicRouting(t *testing.T) {
|
||||||
testRequest(t, ts.URL+"/ab", "", "/:cc")
|
testRequest(t, ts.URL+"/ab", "", "/:cc")
|
||||||
testRequest(t, ts.URL+"/abb", "", "/:cc")
|
testRequest(t, ts.URL+"/abb", "", "/:cc")
|
||||||
testRequest(t, ts.URL+"/abb/cc", "", "/:cc/cc")
|
testRequest(t, ts.URL+"/abb/cc", "", "/:cc/cc")
|
||||||
|
testRequest(t, ts.URL+"/c1/cc", "", "/:cc/cc")
|
||||||
testRequest(t, ts.URL+"/dddaa", "", "/:cc")
|
testRequest(t, ts.URL+"/dddaa", "", "/:cc")
|
||||||
testRequest(t, ts.URL+"/allxxxx", "", "/:cc")
|
testRequest(t, ts.URL+"/allxxxx", "", "/:cc")
|
||||||
testRequest(t, ts.URL+"/alldd", "", "/:cc")
|
testRequest(t, ts.URL+"/alldd", "", "/:cc")
|
||||||
|
|
60
tree.go
60
tree.go
|
@ -418,6 +418,23 @@ type skippedNode struct {
|
||||||
func (n *node) getValue(path string, params *Params, skippedNodes *[]skippedNode, unescape bool) (value nodeValue) {
|
func (n *node) getValue(path string, params *Params, skippedNodes *[]skippedNode, unescape bool) (value nodeValue) {
|
||||||
var globalParamsCount int16
|
var globalParamsCount int16
|
||||||
|
|
||||||
|
rollbackSkipped := func() bool {
|
||||||
|
for l := len(*skippedNodes); l > 0; {
|
||||||
|
skippedNode := (*skippedNodes)[l-1]
|
||||||
|
*skippedNodes = (*skippedNodes)[:l-1]
|
||||||
|
if strings.HasSuffix(skippedNode.path, path) {
|
||||||
|
path = skippedNode.path
|
||||||
|
n = skippedNode.node
|
||||||
|
if value.params != nil {
|
||||||
|
*value.params = (*value.params)[:skippedNode.paramsCount]
|
||||||
|
}
|
||||||
|
globalParamsCount = skippedNode.paramsCount
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
walk: // Outer loop for walking the tree
|
walk: // Outer loop for walking the tree
|
||||||
for {
|
for {
|
||||||
prefix := n.path
|
prefix := n.path
|
||||||
|
@ -457,20 +474,10 @@ walk: // Outer loop for walking the tree
|
||||||
// If the path at the end of the loop is not equal to '/' and the current node has no child nodes
|
// If the path at the end of the loop is not equal to '/' and the current node has no child nodes
|
||||||
// the current node needs to roll back to last valid skippedNode
|
// the current node needs to roll back to last valid skippedNode
|
||||||
if path != "/" {
|
if path != "/" {
|
||||||
for l := len(*skippedNodes); l > 0; {
|
if rollbackSkipped() {
|
||||||
skippedNode := (*skippedNodes)[l-1]
|
|
||||||
*skippedNodes = (*skippedNodes)[:l-1]
|
|
||||||
if strings.HasSuffix(skippedNode.path, path) {
|
|
||||||
path = skippedNode.path
|
|
||||||
n = skippedNode.node
|
|
||||||
if value.params != nil {
|
|
||||||
*value.params = (*value.params)[:skippedNode.paramsCount]
|
|
||||||
}
|
|
||||||
globalParamsCount = skippedNode.paramsCount
|
|
||||||
continue walk
|
continue walk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing found.
|
// Nothing found.
|
||||||
// We can recommend to redirect to the same URL without a
|
// We can recommend to redirect to the same URL without a
|
||||||
|
@ -535,7 +542,11 @@ walk: // Outer loop for walking the tree
|
||||||
// No handle found. Check if a handle for this path + a
|
// No handle found. Check if a handle for this path + a
|
||||||
// trailing slash exists for TSR recommendation
|
// trailing slash exists for TSR recommendation
|
||||||
n = n.children[0]
|
n = n.children[0]
|
||||||
value.tsr = (n.path == "/" && n.handlers != nil) || (n.path == "" && n.indices == "/")
|
if (n.path == "/" && n.handlers != nil) || (n.path == "" && n.indices == "/") {
|
||||||
|
value.tsr = true
|
||||||
|
} else if rollbackSkipped() {
|
||||||
|
continue walk
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -574,21 +585,10 @@ walk: // Outer loop for walking the tree
|
||||||
// If the current path does not equal '/' and the node does not have a registered handle and the most recently matched node has a child node
|
// If the current path does not equal '/' and the node does not have a registered handle and the most recently matched node has a child node
|
||||||
// the current node needs to roll back to last valid skippedNode
|
// the current node needs to roll back to last valid skippedNode
|
||||||
if n.handlers == nil && path != "/" {
|
if n.handlers == nil && path != "/" {
|
||||||
for l := len(*skippedNodes); l > 0; {
|
if rollbackSkipped() {
|
||||||
skippedNode := (*skippedNodes)[l-1]
|
|
||||||
*skippedNodes = (*skippedNodes)[:l-1]
|
|
||||||
if strings.HasSuffix(skippedNode.path, path) {
|
|
||||||
path = skippedNode.path
|
|
||||||
n = skippedNode.node
|
|
||||||
if value.params != nil {
|
|
||||||
*value.params = (*value.params)[:skippedNode.paramsCount]
|
|
||||||
}
|
|
||||||
globalParamsCount = skippedNode.paramsCount
|
|
||||||
continue walk
|
continue walk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// n = latestNode.children[len(latestNode.children)-1]
|
|
||||||
}
|
|
||||||
// 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 {
|
||||||
|
@ -626,20 +626,10 @@ walk: // Outer loop for walking the tree
|
||||||
|
|
||||||
// roll back to last valid skippedNode
|
// roll back to last valid skippedNode
|
||||||
if !value.tsr && path != "/" {
|
if !value.tsr && path != "/" {
|
||||||
for l := len(*skippedNodes); l > 0; {
|
if rollbackSkipped() {
|
||||||
skippedNode := (*skippedNodes)[l-1]
|
|
||||||
*skippedNodes = (*skippedNodes)[:l-1]
|
|
||||||
if strings.HasSuffix(skippedNode.path, path) {
|
|
||||||
path = skippedNode.path
|
|
||||||
n = skippedNode.node
|
|
||||||
if value.params != nil {
|
|
||||||
*value.params = (*value.params)[:skippedNode.paramsCount]
|
|
||||||
}
|
|
||||||
globalParamsCount = skippedNode.paramsCount
|
|
||||||
continue walk
|
continue walk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,7 @@ func TestTreeWildcard(t *testing.T) {
|
||||||
{"/aaa/cc", false, "/:cc/cc", Params{Param{Key: "cc", Value: "aaa"}}},
|
{"/aaa/cc", false, "/:cc/cc", Params{Param{Key: "cc", Value: "aaa"}}},
|
||||||
{"/ab", false, "/:cc", Params{Param{Key: "cc", Value: "ab"}}},
|
{"/ab", false, "/:cc", Params{Param{Key: "cc", Value: "ab"}}},
|
||||||
{"/abb", false, "/:cc", Params{Param{Key: "cc", Value: "abb"}}},
|
{"/abb", false, "/:cc", Params{Param{Key: "cc", Value: "abb"}}},
|
||||||
|
{"/c1/cc", false, "/:cc/cc", Params{Param{Key: "cc", Value: "c1"}}},
|
||||||
{"/abb/cc", false, "/:cc/cc", Params{Param{Key: "cc", Value: "abb"}}},
|
{"/abb/cc", false, "/:cc/cc", Params{Param{Key: "cc", Value: "abb"}}},
|
||||||
{"/allxxxx", false, "/:cc", Params{Param{Key: "cc", Value: "allxxxx"}}},
|
{"/allxxxx", false, "/:cc", Params{Param{Key: "cc", Value: "allxxxx"}}},
|
||||||
{"/alldd", false, "/:cc", Params{Param{Key: "cc", Value: "alldd"}}},
|
{"/alldd", false, "/:cc", Params{Param{Key: "cc", Value: "alldd"}}},
|
||||||
|
@ -266,6 +267,8 @@ func TestTreeWildcard(t *testing.T) {
|
||||||
{"/something/secondthingaaaa/thirdthing", false, "/something/:paramname/thirdthing", Params{Param{Key: "paramname", Value: "secondthingaaaa"}}},
|
{"/something/secondthingaaaa/thirdthing", false, "/something/:paramname/thirdthing", Params{Param{Key: "paramname", Value: "secondthingaaaa"}}},
|
||||||
{"/something/se/thirdthing", false, "/something/:paramname/thirdthing", Params{Param{Key: "paramname", Value: "se"}}},
|
{"/something/se/thirdthing", false, "/something/:paramname/thirdthing", Params{Param{Key: "paramname", Value: "se"}}},
|
||||||
{"/something/s/thirdthing", false, "/something/:paramname/thirdthing", Params{Param{Key: "paramname", Value: "s"}}},
|
{"/something/s/thirdthing", false, "/something/:paramname/thirdthing", Params{Param{Key: "paramname", Value: "s"}}},
|
||||||
|
{"/c1/dd/ee", false, "/:cc/:dd/ee", Params{Param{Key: "cc", Value: "c1"}, Param{Key: "dd", Value: "dd"}}},
|
||||||
|
{"/c1/dd/ee/", true, "/:cc/:dd/ee", Params{Param{Key: "cc", Value: "c1"}, Param{Key: "dd", Value: "dd"}}},
|
||||||
{"/c/d/ee", false, "/:cc/:dd/ee", Params{Param{Key: "cc", Value: "c"}, Param{Key: "dd", Value: "d"}}},
|
{"/c/d/ee", false, "/:cc/:dd/ee", Params{Param{Key: "cc", Value: "c"}, Param{Key: "dd", Value: "d"}}},
|
||||||
{"/c/d/e/ff", false, "/:cc/:dd/:ee/ff", Params{Param{Key: "cc", Value: "c"}, Param{Key: "dd", Value: "d"}, Param{Key: "ee", Value: "e"}}},
|
{"/c/d/e/ff", false, "/:cc/:dd/:ee/ff", Params{Param{Key: "cc", Value: "c"}, Param{Key: "dd", Value: "d"}, Param{Key: "ee", Value: "e"}}},
|
||||||
{"/c/d/e/f/gg", false, "/:cc/:dd/:ee/:ff/gg", Params{Param{Key: "cc", Value: "c"}, Param{Key: "dd", Value: "d"}, Param{Key: "ee", Value: "e"}, Param{Key: "ff", Value: "f"}}},
|
{"/c/d/e/f/gg", false, "/:cc/:dd/:ee/:ff/gg", Params{Param{Key: "cc", Value: "c"}, Param{Key: "dd", Value: "d"}, Param{Key: "ee", Value: "e"}, Param{Key: "ff", Value: "f"}}},
|
||||||
|
@ -474,7 +477,7 @@ func TestTreeDuplicatePath(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printChildren(tree, "")
|
// printChildren(tree, "")
|
||||||
|
|
||||||
checkRequests(t, tree, testRequests{
|
checkRequests(t, tree, testRequests{
|
||||||
{"/", false, "/", nil},
|
{"/", false, "/", nil},
|
||||||
|
|
Loading…
Reference in New Issue