20 Star 164 Fork 26

qiqi / orange

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
lookup.go 3.87 KB
一键复制 编辑 原始数据 按行查看 历史
package app
import (
"net/http"
)
var (
methods = [...]string{
http.MethodGet,
http.MethodPost,
http.MethodDelete,
http.MethodPut,
http.MethodConnect,
http.MethodHead,
http.MethodOptions,
http.MethodPatch,
http.MethodTrace,
}
)
// Find 路由查找匹配到符合条件的url
func (r *Router) Find(method, path string, ctx *Context) (httpHandler HandlerFunc, httpMiddleware []MiddleWare) {
ctx.path = path
cn := r.tree // Current node as root
var (
search = path
child *node // Child node
n int // Param counter
nk kind // Next kind
nn *node // Next node
ns string // Next search
pvalues = ctx.pvalues
)
// Search order static > param > any
for {
if search == "" {
break
}
pl := 0 // Prefix length
l := 0 // LCP length
if cn.label != ':' {
sl := len(search)
pl = len(cn.prefix)
// LCP
max := pl
if sl < max {
max = sl
}
for ; l < max && search[l] == cn.prefix[l]; l++ {
}
}
if l == pl {
// Continue search
search = search[l:]
} else {
cn = nn
search = ns
if nk == pkind {
goto Param
} else if nk == akind {
goto Any
}
// Not found
return
}
if search == "" {
break
}
// Static node
if child = cn.findChild(search[0], skind); child != nil {
// Save next
if cn.prefix[len(cn.prefix)-1] == '/' {
nk = pkind
nn = cn
ns = search
}
cn = child
continue
}
// Param node
Param:
if child = cn.findChildByKind(pkind); child != nil {
if len(pvalues) == n {
continue
}
// Save next
if cn.prefix[len(cn.prefix)-1] == '/' {
nk = akind
nn = cn
ns = search
}
cn = child
i, l := 0, len(search)
for ; i < l && search[i] != '/'; i++ {
}
pvalues[n] = search[:i]
n++
search = search[i:]
continue
}
// Any node
Any:
if cn = cn.findChildByKind(akind); cn == nil {
if nn != nil {
cn = nn
nn = cn.parent
search = ns
if nk == pkind {
goto Param
} else if nk == akind {
goto Any
}
}
// Not found
return
}
pvalues[len(cn.pnames)-1] = search
break
}
httpHandler = cn.findHandler(method)
ctx.path = cn.ppath
ctx.pnames = cn.pnames
if m, ok := routers.middlewareMap[cn.ppath]; ok == true {
httpMiddleware = m
}
if httpHandler == nil {
httpHandler = cn.checkMethodNotAllowed()
if cn = cn.findChildByKind(akind); cn == nil {
return
}
if h := cn.findHandler(method); h != nil {
httpHandler = h
} else {
httpHandler = cn.checkMethodNotAllowed()
}
ctx.path = cn.ppath
ctx.pnames = cn.pnames
pvalues[len(cn.pnames)-1] = ""
}
ctx.pvalues = pvalues
return
}
func (n *node) findHandler(method string) (httpHandler HandlerFunc) {
switch method {
case methodGRPC:
httpHandler = n.methodHandler.grpc
case http.MethodConnect:
httpHandler = n.methodHandler.connect
case http.MethodDelete:
httpHandler = n.methodHandler.delete
case http.MethodGet:
httpHandler = n.methodHandler.get
case http.MethodHead:
httpHandler = n.methodHandler.head
case http.MethodOptions:
httpHandler = n.methodHandler.options
case http.MethodPatch:
httpHandler = n.methodHandler.patch
case http.MethodPost:
httpHandler = n.methodHandler.post
case http.MethodPut:
httpHandler = n.methodHandler.put
case http.MethodTrace:
httpHandler = n.methodHandler.trace
default:
}
if n.methodHandler.any != nil {
httpHandler = n.methodHandler.any
}
return httpHandler
}
func (n *node) findChild(l byte, t kind) *node {
for _, c := range n.children {
if c.label == l && c.kind == t {
return c
}
}
return nil
}
func (n *node) findChildByKind(t kind) *node {
for _, c := range n.children {
if c.kind == t {
return c
}
}
return nil
}
func (n *node) checkMethodNotAllowed() HandlerFunc {
for _, m := range methods {
if h := n.findHandler(m); h != nil {
return MethodNotAllowedHandler
}
}
return NotFoundHandler
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/zhucheer/orange.git
git@gitee.com:zhucheer/orange.git
zhucheer
orange
orange
v0.5.2

搜索帮助

344bd9b3 5694891 D2dac590 5694891