mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-19 07:38:57 +08:00
update
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
parent
717b2145d4
commit
9e8404975e
44
gin.go
44
gin.go
@ -113,6 +113,8 @@ type Engine struct {
|
|||||||
noMethod HandlersChain
|
noMethod HandlersChain
|
||||||
pool sync.Pool
|
pool sync.Pool
|
||||||
trees methodTrees
|
trees methodTrees
|
||||||
|
// paramsPool sync.Pool
|
||||||
|
maxParams uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ IRouter = &Engine{}
|
var _ IRouter = &Engine{}
|
||||||
@ -256,6 +258,8 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
|
|||||||
assert1(len(handlers) > 0, "there must be at least one handler")
|
assert1(len(handlers) > 0, "there must be at least one handler")
|
||||||
|
|
||||||
debugPrintRoute(method, path, handlers)
|
debugPrintRoute(method, path, handlers)
|
||||||
|
// varsCount := uint16(0)
|
||||||
|
|
||||||
root := engine.trees.get(method)
|
root := engine.trees.get(method)
|
||||||
if root == nil {
|
if root == nil {
|
||||||
root = new(node)
|
root = new(node)
|
||||||
@ -263,6 +267,19 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
|
|||||||
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)
|
||||||
|
|
||||||
|
// Update maxParams
|
||||||
|
// if paramsCount := countParams(path); paramsCount+varsCount > root.maxParams {
|
||||||
|
// engine.maxParams = paramsCount + varsCount
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Lazy-init paramsPool alloc func
|
||||||
|
// if engine.paramsPool.New == nil && engine.maxParams > 0 {
|
||||||
|
// engine.paramsPool.New = func() interface{} {
|
||||||
|
// ps := make(Params, 0, engine.maxParams)
|
||||||
|
// return &ps
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routes returns a slice of registered routes, including some useful information, such as:
|
// Routes returns a slice of registered routes, including some useful information, such as:
|
||||||
@ -381,6 +398,23 @@ func (engine *Engine) HandleContext(c *Context) {
|
|||||||
c.index = oldIndexValue
|
c.index = oldIndexValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func (engine *Engine) getParams() *Params {
|
||||||
|
// // c := engine.pool.Get().(*Context)
|
||||||
|
// // c.Params = c.Params[0:0]
|
||||||
|
// ps := engine.paramsPool.Get().(*Params)
|
||||||
|
// *ps = (*ps)[0:0] // reset slice
|
||||||
|
// return ps
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (engine *Engine) putParams(ps *Params) {
|
||||||
|
// // c := engine.pool.Get().(*Context)
|
||||||
|
// // c.Params = *ps
|
||||||
|
// // engine.pool.Put(c)
|
||||||
|
// if ps != nil {
|
||||||
|
// engine.paramsPool.Put(ps)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
func (engine *Engine) handleHTTPRequest(c *Context) {
|
func (engine *Engine) handleHTTPRequest(c *Context) {
|
||||||
httpMethod := c.Request.Method
|
httpMethod := c.Request.Method
|
||||||
rPath := c.Request.URL.Path
|
rPath := c.Request.URL.Path
|
||||||
@ -402,10 +436,16 @@ func (engine *Engine) handleHTTPRequest(c *Context) {
|
|||||||
}
|
}
|
||||||
root := t[i].root
|
root := t[i].root
|
||||||
// Find route in tree
|
// Find route in tree
|
||||||
value := root.getValue(rPath, c.Params, unescape)
|
value := root.getValue(rPath, &c.Params, unescape)
|
||||||
|
if value.params != nil {
|
||||||
|
// engine.putParams(value.params)
|
||||||
|
c.Params = *value.params
|
||||||
|
}
|
||||||
if value.handlers != nil {
|
if value.handlers != nil {
|
||||||
c.handlers = value.handlers
|
c.handlers = value.handlers
|
||||||
c.Params = value.params
|
// if value.params != nil {
|
||||||
|
// c.Params = *value.params
|
||||||
|
// }
|
||||||
// c.fullPath = value.fullPath
|
// c.fullPath = value.fullPath
|
||||||
c.Next()
|
c.Next()
|
||||||
c.writermem.WriteHeaderNow()
|
c.writermem.WriteHeaderNow()
|
||||||
|
306
tree.go
306
tree.go
@ -5,7 +5,6 @@
|
|||||||
package gin
|
package gin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@ -132,23 +131,23 @@ func (n *node) incrementChildPrio(pos int) int {
|
|||||||
func (n *node) addRoute(path string, handlers HandlersChain) {
|
func (n *node) addRoute(path string, handlers HandlersChain) {
|
||||||
fullPath := path
|
fullPath := path
|
||||||
n.priority++
|
n.priority++
|
||||||
numParams := countParams(path)
|
// numParams := countParams(path)
|
||||||
|
|
||||||
// Empty tree
|
// Empty tree
|
||||||
if len(n.path) == 0 && len(n.children) == 0 {
|
if len(n.path) == 0 && len(n.children) == 0 {
|
||||||
n.insertChild(numParams, path, fullPath, handlers)
|
n.insertChild(path, fullPath, handlers)
|
||||||
n.nType = root
|
n.nType = root
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
parentFullPathIndex := 0
|
// parentFullPathIndex := 0
|
||||||
|
|
||||||
walk:
|
walk:
|
||||||
for {
|
for {
|
||||||
// Update maxParams of the current node
|
// Update maxParams of the current node
|
||||||
if numParams > n.maxParams {
|
// if numParams > n.maxParams {
|
||||||
n.maxParams = numParams
|
// n.maxParams = numParams
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Find the longest common prefix.
|
// Find the longest common prefix.
|
||||||
// This also implies that the common prefix contains no ':' or '*'
|
// This also implies that the common prefix contains no ':' or '*'
|
||||||
@ -168,11 +167,11 @@ walk:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update maxParams (max of all children)
|
// Update maxParams (max of all children)
|
||||||
for _, v := range child.children {
|
// for _, v := range child.children {
|
||||||
if v.maxParams > child.maxParams {
|
// if v.maxParams > child.maxParams {
|
||||||
child.maxParams = v.maxParams
|
// child.maxParams = v.maxParams
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
n.children = []*node{&child}
|
n.children = []*node{&child}
|
||||||
// []byte for proper unicode char conversion, see #65
|
// []byte for proper unicode char conversion, see #65
|
||||||
@ -188,15 +187,15 @@ walk:
|
|||||||
path = path[i:]
|
path = path[i:]
|
||||||
|
|
||||||
if n.wildChild {
|
if n.wildChild {
|
||||||
parentFullPathIndex += len(n.path)
|
// parentFullPathIndex += len(n.path)
|
||||||
n = n.children[0]
|
n = n.children[0]
|
||||||
n.priority++
|
n.priority++
|
||||||
|
|
||||||
// Update maxParams of the child node
|
// Update maxParams of the child node
|
||||||
if numParams > n.maxParams {
|
// if numParams > n.maxParams {
|
||||||
n.maxParams = numParams
|
// n.maxParams = numParams
|
||||||
}
|
// }
|
||||||
numParams--
|
// numParams--
|
||||||
|
|
||||||
// Check if the wildcard matches
|
// Check if the wildcard matches
|
||||||
if len(path) >= len(n.path) && n.path == path[:len(n.path)] {
|
if len(path) >= len(n.path) && n.path == path[:len(n.path)] {
|
||||||
@ -222,7 +221,7 @@ walk:
|
|||||||
|
|
||||||
// slash after param
|
// slash after param
|
||||||
if n.nType == param && c == '/' && len(n.children) == 1 {
|
if n.nType == param && c == '/' && len(n.children) == 1 {
|
||||||
parentFullPathIndex += len(n.path)
|
// parentFullPathIndex += len(n.path)
|
||||||
n = n.children[0]
|
n = n.children[0]
|
||||||
n.priority++
|
n.priority++
|
||||||
continue walk
|
continue walk
|
||||||
@ -231,7 +230,7 @@ walk:
|
|||||||
// Check if a child with the next path byte exists
|
// Check if a child with the next path byte exists
|
||||||
for i, max := 0, len(n.indices); i < max; i++ {
|
for i, max := 0, len(n.indices); i < max; i++ {
|
||||||
if c == n.indices[i] {
|
if c == n.indices[i] {
|
||||||
parentFullPathIndex += len(n.path)
|
// parentFullPathIndex += len(n.path)
|
||||||
i = n.incrementChildPrio(i)
|
i = n.incrementChildPrio(i)
|
||||||
n = n.children[i]
|
n = n.children[i]
|
||||||
continue walk
|
continue walk
|
||||||
@ -243,14 +242,14 @@ walk:
|
|||||||
// []byte for proper unicode char conversion, see #65
|
// []byte for proper unicode char conversion, see #65
|
||||||
n.indices += string([]byte{c})
|
n.indices += string([]byte{c})
|
||||||
child := &node{
|
child := &node{
|
||||||
maxParams: numParams,
|
// maxParams: numParams,
|
||||||
// fullPath: fullPath,
|
// 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)
|
||||||
n = child
|
n = child
|
||||||
}
|
}
|
||||||
n.insertChild(numParams, path, fullPath, handlers)
|
n.insertChild(path, fullPath, handlers)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,8 +287,8 @@ func findWildcard(path string) (wildcard string, i int, valid bool) {
|
|||||||
return "", -1, false
|
return "", -1, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) insertChild(numParams uint16, path string, fullPath string, handlers HandlersChain) {
|
func (n *node) insertChild(path string, fullPath string, handlers HandlersChain) {
|
||||||
for numParams > 0 {
|
for {
|
||||||
// Find prefix until first wildcard
|
// Find prefix until first wildcard
|
||||||
wildcard, i, valid := findWildcard(path)
|
wildcard, i, valid := findWildcard(path)
|
||||||
if i < 0 { // No wildcard found
|
if i < 0 { // No wildcard found
|
||||||
@ -325,13 +324,13 @@ func (n *node) insertChild(numParams uint16, path string, fullPath string, handl
|
|||||||
child := &node{
|
child := &node{
|
||||||
nType: param,
|
nType: param,
|
||||||
path: wildcard,
|
path: wildcard,
|
||||||
maxParams: numParams,
|
// maxParams: numParams,
|
||||||
// fullPath: fullPath,
|
// fullPath: fullPath,
|
||||||
}
|
}
|
||||||
n.children = []*node{child}
|
n.children = []*node{child}
|
||||||
n = child
|
n = child
|
||||||
n.priority++
|
n.priority++
|
||||||
numParams--
|
// numParams--
|
||||||
|
|
||||||
// if the path doesn't end with the wildcard, then there
|
// if the path doesn't end with the wildcard, then there
|
||||||
// will be another non-wildcard subpath starting with '/'
|
// will be another non-wildcard subpath starting with '/'
|
||||||
@ -339,7 +338,7 @@ func (n *node) insertChild(numParams uint16, path string, fullPath string, handl
|
|||||||
path = path[len(wildcard):]
|
path = path[len(wildcard):]
|
||||||
|
|
||||||
child := &node{
|
child := &node{
|
||||||
maxParams: numParams,
|
// maxParams: numParams,
|
||||||
priority: 1,
|
priority: 1,
|
||||||
// fullPath: fullPath,
|
// fullPath: fullPath,
|
||||||
}
|
}
|
||||||
@ -354,7 +353,7 @@ func (n *node) insertChild(numParams uint16, path string, fullPath string, handl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// catchAll
|
// catchAll
|
||||||
if i+len(wildcard) != len(path) || numParams > 1 {
|
if i+len(wildcard) != len(path) {
|
||||||
panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
|
panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,13 +373,13 @@ func (n *node) insertChild(numParams uint16, path string, fullPath string, handl
|
|||||||
child := &node{
|
child := &node{
|
||||||
wildChild: true,
|
wildChild: true,
|
||||||
nType: catchAll,
|
nType: catchAll,
|
||||||
maxParams: 1,
|
// maxParams: 1,
|
||||||
// fullPath: fullPath,
|
// fullPath: fullPath,
|
||||||
}
|
}
|
||||||
// update maxParams of the parent node
|
// update maxParams of the parent node
|
||||||
if n.maxParams < 1 {
|
// if n.maxParams < 1 {
|
||||||
n.maxParams = 1
|
// n.maxParams = 1
|
||||||
}
|
// }
|
||||||
n.children = []*node{child}
|
n.children = []*node{child}
|
||||||
n.indices = string('/')
|
n.indices = string('/')
|
||||||
n = child
|
n = child
|
||||||
@ -392,7 +391,7 @@ func (n *node) insertChild(numParams uint16, path string, fullPath string, handl
|
|||||||
nType: catchAll,
|
nType: catchAll,
|
||||||
handlers: handlers,
|
handlers: handlers,
|
||||||
priority: 1,
|
priority: 1,
|
||||||
maxParams: 1,
|
// maxParams: 1,
|
||||||
// fullPath: fullPath,
|
// fullPath: fullPath,
|
||||||
}
|
}
|
||||||
n.children = []*node{child}
|
n.children = []*node{child}
|
||||||
@ -409,7 +408,7 @@ func (n *node) insertChild(numParams uint16, path string, fullPath string, handl
|
|||||||
// nodeValue holds return values of (*Node).getValue method
|
// 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
|
// fullPath string
|
||||||
}
|
}
|
||||||
@ -419,11 +418,148 @@ type nodeValue struct {
|
|||||||
// If no handle can be found, a TSR (trailing slash redirect) recommendation is
|
// If no handle can be found, a TSR (trailing slash redirect) recommendation is
|
||||||
// made if a handle exists with an extra (without the) trailing slash for the
|
// made if a handle exists with an extra (without the) trailing slash for the
|
||||||
// given path.
|
// given path.
|
||||||
func (n *node) getValue(path string, po Params, unescape bool) (value nodeValue) {
|
func (n *node) getValue(path string, params *Params, unescape bool) (value nodeValue) {
|
||||||
value.params = po
|
value = nodeValue{}
|
||||||
walk: // Outer loop for walking the tree
|
walk: // Outer loop for walking the tree
|
||||||
for {
|
for {
|
||||||
prefix := n.path
|
prefix := n.path
|
||||||
|
|
||||||
|
if len(path) > len(prefix) && path[:len(prefix)] == prefix {
|
||||||
|
path = path[len(prefix):]
|
||||||
|
// If this node does not have a wildcard (param or catchAll)
|
||||||
|
// child, we can just look up the next child node and continue
|
||||||
|
// to walk down the tree
|
||||||
|
if !n.wildChild {
|
||||||
|
idxc := path[0]
|
||||||
|
for i, c := range []byte(n.indices) {
|
||||||
|
if c == idxc {
|
||||||
|
n = n.children[i]
|
||||||
|
continue walk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing found.
|
||||||
|
// We can recommend to redirect to the same URL without a
|
||||||
|
// trailing slash if a leaf exists for that path.
|
||||||
|
value.tsr = (path == "/" && n.handlers != nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle wildcard child
|
||||||
|
n = n.children[0]
|
||||||
|
switch n.nType {
|
||||||
|
case param:
|
||||||
|
// find param end (either '/' or path end)
|
||||||
|
end := 0
|
||||||
|
for end < len(path) && path[end] != '/' {
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
|
||||||
|
// save param value
|
||||||
|
// if cap(value.params) < int(n.maxParams) {
|
||||||
|
// value.params = make(Params, 0, n.maxParams)
|
||||||
|
// }
|
||||||
|
// i := len(value.params)
|
||||||
|
// value.params = value.params[:i+1] // expand slice within preallocated capacity
|
||||||
|
// value.params[i].Key = n.path[1:]
|
||||||
|
// val := path[:end]
|
||||||
|
// if unescape {
|
||||||
|
// var err error
|
||||||
|
// if value.params[i].Value, err = url.QueryUnescape(val); err != nil {
|
||||||
|
// value.params[i].Value = val // fallback, in case of error
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// value.params[i].Value = val
|
||||||
|
// }
|
||||||
|
if params != nil {
|
||||||
|
if value.params == nil {
|
||||||
|
value.params = params
|
||||||
|
}
|
||||||
|
// Expand slice within preallocated capacity
|
||||||
|
i := len(*value.params)
|
||||||
|
*value.params = (*value.params)[:i+1]
|
||||||
|
// val := path[:end]
|
||||||
|
// if unescape {
|
||||||
|
// if v, err := url.QueryUnescape(val); err == nil {
|
||||||
|
// val = v
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
(*value.params)[i] = Param{
|
||||||
|
Key: n.path[1:],
|
||||||
|
Value: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to go deeper!
|
||||||
|
if end < len(path) {
|
||||||
|
if len(n.children) > 0 {
|
||||||
|
path = path[end:]
|
||||||
|
n = n.children[0]
|
||||||
|
continue walk
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... but we can't
|
||||||
|
value.tsr = (len(path) == end+1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.handlers = n.handlers; value.handlers != nil {
|
||||||
|
// value.fullPath = n.fullPath
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(n.children) == 1 {
|
||||||
|
// No handle found. Check if a handle for this path + a
|
||||||
|
// trailing slash exists for TSR recommendation
|
||||||
|
n = n.children[0]
|
||||||
|
value.tsr = (n.path == "/" && n.handlers != nil)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
case catchAll:
|
||||||
|
// // save param value
|
||||||
|
// if cap(value.params) < int(n.maxParams) {
|
||||||
|
// value.params = make(Params, 0, n.maxParams)
|
||||||
|
// }
|
||||||
|
// i := len(value.params)
|
||||||
|
// value.params = value.params[:i+1] // expand slice within preallocated capacity
|
||||||
|
// value.params[i].Key = n.path[2:]
|
||||||
|
// if unescape {
|
||||||
|
// var err error
|
||||||
|
// if value.params[i].Value, err = url.QueryUnescape(path); err != nil {
|
||||||
|
// value.params[i].Value = path // fallback, in case of error
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// value.params[i].Value = path
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Save param value
|
||||||
|
if params != nil {
|
||||||
|
if value.params == nil {
|
||||||
|
value.params = params
|
||||||
|
}
|
||||||
|
// Expand slice within preallocated capacity
|
||||||
|
i := len(*value.params)
|
||||||
|
*value.params = (*value.params)[:i+1]
|
||||||
|
// if unescape {
|
||||||
|
// if v, err := url.QueryUnescape(path); err == nil {
|
||||||
|
// path = v
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
(*value.params)[i] = Param{
|
||||||
|
Key: n.path[2:],
|
||||||
|
Value: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value.handlers = n.handlers
|
||||||
|
// value.fullPath = n.fullPath
|
||||||
|
return
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("invalid node type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if path == prefix {
|
if path == prefix {
|
||||||
// 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.
|
||||||
@ -454,106 +590,6 @@ walk: // Outer loop for walking the tree
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(path) > len(prefix) && path[:len(prefix)] == prefix {
|
|
||||||
path = path[len(prefix):]
|
|
||||||
// If this node does not have a wildcard (param or catchAll)
|
|
||||||
// child, we can just look up the next child node and continue
|
|
||||||
// to walk down the tree
|
|
||||||
if !n.wildChild {
|
|
||||||
c := path[0]
|
|
||||||
indices := n.indices
|
|
||||||
for i, max := 0, len(indices); i < max; i++ {
|
|
||||||
if c == indices[i] {
|
|
||||||
n = n.children[i]
|
|
||||||
continue walk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing found.
|
|
||||||
// We can recommend to redirect to the same URL without a
|
|
||||||
// trailing slash if a leaf exists for that path.
|
|
||||||
value.tsr = path == "/" && n.handlers != nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle wildcard child
|
|
||||||
n = n.children[0]
|
|
||||||
switch n.nType {
|
|
||||||
case param:
|
|
||||||
// find param end (either '/' or path end)
|
|
||||||
end := 0
|
|
||||||
for end < len(path) && path[end] != '/' {
|
|
||||||
end++
|
|
||||||
}
|
|
||||||
|
|
||||||
// save param value
|
|
||||||
if cap(value.params) < int(n.maxParams) {
|
|
||||||
value.params = make(Params, 0, n.maxParams)
|
|
||||||
}
|
|
||||||
i := len(value.params)
|
|
||||||
value.params = value.params[:i+1] // expand slice within preallocated capacity
|
|
||||||
value.params[i].Key = n.path[1:]
|
|
||||||
val := path[:end]
|
|
||||||
if unescape {
|
|
||||||
var err error
|
|
||||||
if value.params[i].Value, err = url.QueryUnescape(val); err != nil {
|
|
||||||
value.params[i].Value = val // fallback, in case of error
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value.params[i].Value = val
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to go deeper!
|
|
||||||
if end < len(path) {
|
|
||||||
if len(n.children) > 0 {
|
|
||||||
path = path[end:]
|
|
||||||
n = n.children[0]
|
|
||||||
continue walk
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... but we can't
|
|
||||||
value.tsr = len(path) == end+1
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.handlers = n.handlers; value.handlers != nil {
|
|
||||||
// value.fullPath = n.fullPath
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(n.children) == 1 {
|
|
||||||
// No handle found. Check if a handle for this path + a
|
|
||||||
// trailing slash exists for TSR recommendation
|
|
||||||
n = n.children[0]
|
|
||||||
value.tsr = n.path == "/" && n.handlers != nil
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
case catchAll:
|
|
||||||
// save param value
|
|
||||||
if cap(value.params) < int(n.maxParams) {
|
|
||||||
value.params = make(Params, 0, n.maxParams)
|
|
||||||
}
|
|
||||||
i := len(value.params)
|
|
||||||
value.params = value.params[:i+1] // expand slice within preallocated capacity
|
|
||||||
value.params[i].Key = n.path[2:]
|
|
||||||
if unescape {
|
|
||||||
var err error
|
|
||||||
if value.params[i].Value, err = url.QueryUnescape(path); err != nil {
|
|
||||||
value.params[i].Value = path // fallback, in case of error
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value.params[i].Value = path
|
|
||||||
}
|
|
||||||
|
|
||||||
value.handlers = n.handlers
|
|
||||||
// value.fullPath = n.fullPath
|
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
panic("invalid node type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing found. We can recommend to redirect to the same URL with an
|
// Nothing found. We can recommend to redirect to the same URL with an
|
||||||
// extra trailing slash if a leaf exists for that path
|
// extra trailing slash if a leaf exists for that path
|
||||||
value.tsr = (path == "/") ||
|
value.tsr = (path == "/") ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user