echoip/http/router.go

74 lines
1.4 KiB
Go
Raw Normal View History

2018-03-18 22:15:51 +01:00
package http
import (
"net/http"
"strings"
)
type router struct {
routes []*route
}
type route struct {
2018-03-19 19:44:14 +01:00
method string
path string
prefix bool
handler appHandler
matcherFunc func(*http.Request) bool
2018-03-18 22:15:51 +01:00
}
func NewRouter() *router {
return &router{}
}
func (r *router) Route(method, path string, handler appHandler) *route {
route := route{
method: method,
path: path,
handler: handler,
}
r.routes = append(r.routes, &route)
return &route
}
func (r *router) RoutePrefix(method, path string, handler appHandler) *route {
route := r.Route(method, path, handler)
route.prefix = true
return route
}
func (r *router) Handler() http.Handler {
return appHandler(func(w http.ResponseWriter, req *http.Request) *appError {
for _, route := range r.routes {
if route.match(req) {
return route.handler(w, req)
}
}
return NotFoundHandler(w, req)
})
}
2018-03-19 19:44:14 +01:00
func (r *route) Header(header, value string) {
r.MatcherFunc(func(req *http.Request) bool {
2018-03-18 22:15:51 +01:00
return req.Header.Get(header) == value
})
}
2018-03-19 19:44:14 +01:00
func (r *route) MatcherFunc(f func(*http.Request) bool) {
r.matcherFunc = f
2018-03-18 22:15:51 +01:00
}
func (r *route) match(req *http.Request) bool {
if req.Method != r.method {
return false
}
if r.prefix {
if !strings.HasPrefix(req.URL.Path, r.path) {
return false
}
} else if r.path != req.URL.Path {
return false
}
2018-03-19 19:44:14 +01:00
return r.matcherFunc == nil || r.matcherFunc(req)
2018-03-18 22:15:51 +01:00
}