Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
Bo-Yi Wu 2020-05-08 13:12:41 +08:00
parent 71f841a1f5
commit fe436bf2c0
2 changed files with 124 additions and 125 deletions

5
gin.go
View File

@ -253,6 +253,7 @@ func (engine *Engine) rebuild405Handlers() {
}
func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
// log.Println(method, path)
assert1(path[0] == '/', "path must begin with '/'")
assert1(method != "", "HTTP method can not be empty")
assert1(len(handlers) > 0, "there must be at least one handler")
@ -269,13 +270,15 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
root.addRoute(path, handlers)
// Update maxParams
if paramsCount := countParams(path); paramsCount+varsCount > root.maxParams {
// log.Println("countParams(path):", countParams(path))
if paramsCount := countParams(path); paramsCount+varsCount > engine.maxParams {
engine.maxParams = paramsCount + varsCount
}
// Lazy-init paramsPool alloc func
if engine.paramsPool.New == nil && engine.maxParams > 0 {
engine.paramsPool.New = func() interface{} {
// log.Println("engine.maxParams:", engine.maxParams)
ps := make(Params, 0, engine.maxParams)
return &ps
}

244
tree.go
View File

@ -5,7 +5,6 @@
package gin
import (
"log"
"strings"
"unicode"
"unicode/utf8"
@ -424,146 +423,143 @@ func (n *node) getValue(path string, params func() *Params, unescape bool) (valu
walk: // Outer loop for walking the tree
for {
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
if len(path) > len(prefix) {
if 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
}
// 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()
// 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++
}
// Expand slice within preallocated capacity
i := len(*value.params)
log.Println(i)
log.Println(*value.params)
*value.params = (*value.params)[:i+1]
// 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 {
// if v, err := url.QueryUnescape(val); err == nil {
// val = v
// 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
// }
(*value.params)[i] = Param{
Key: n.path[1:],
Value: path,
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[:end],
}
}
}
// we need to go deeper!
if end < len(path) {
if len(n.children) > 0 {
path = path[end:]
// 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]
continue walk
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,
}
}
// ... but we can't
value.tsr = (len(path) == end+1)
return
}
if value.handlers = n.handlers; value.handlers != nil {
value.handlers = n.handlers
// value.fullPath = n.fullPath
return
default:
panic("invalid node type")
}
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 {
} else if path == prefix {
// We should have reached the node containing the handle.
// Check if this node has a handle registered.
if value.handlers = n.handlers; value.handlers != nil {