package web
|
|
|
|
import "net/http"
|
|
|
|
type routeMachine struct {
|
|
sm stateMachine
|
|
routes []route
|
|
}
|
|
|
|
func matchRoute(route route, m method, ms *method, r *http.Request, c *C) bool {
|
|
if !route.pattern.Match(r, c) {
|
|
return false
|
|
}
|
|
*ms |= route.method
|
|
|
|
if route.method&m != 0 {
|
|
route.pattern.Run(r, c)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (rm routeMachine) route(c *C, w http.ResponseWriter, r *http.Request) (method, *route) {
|
|
m := httpMethod(r.Method)
|
|
var methods method
|
|
p := r.URL.Path
|
|
|
|
if len(rm.sm) == 0 {
|
|
return methods, nil
|
|
}
|
|
|
|
var i int
|
|
for {
|
|
sm := rm.sm[i].mode
|
|
if sm&smSetCursor != 0 {
|
|
si := rm.sm[i].i
|
|
p = r.URL.Path[si:]
|
|
i++
|
|
continue
|
|
}
|
|
|
|
length := int(sm & smLengthMask)
|
|
match := false
|
|
if length <= len(p) {
|
|
bs := rm.sm[i].bs
|
|
switch length {
|
|
case 3:
|
|
if p[2] != bs[2] {
|
|
break
|
|
}
|
|
fallthrough
|
|
case 2:
|
|
if p[1] != bs[1] {
|
|
break
|
|
}
|
|
fallthrough
|
|
case 1:
|
|
if p[0] != bs[0] {
|
|
break
|
|
}
|
|
fallthrough
|
|
case 0:
|
|
p = p[length:]
|
|
match = true
|
|
}
|
|
}
|
|
|
|
if match && sm&smRoute != 0 {
|
|
si := rm.sm[i].i
|
|
if matchRoute(rm.routes[si], m, &methods, r, c) {
|
|
return 0, &rm.routes[si]
|
|
}
|
|
i++
|
|
} else if match != (sm&smJumpOnMatch == 0) {
|
|
if sm&smFail != 0 {
|
|
return methods, nil
|
|
}
|
|
i = int(rm.sm[i].i)
|
|
} else {
|
|
i++
|
|
}
|
|
}
|
|
}
|