86 lines
1.5 KiB
Go
86 lines
1.5 KiB
Go
package httpx
|
|
|
|
import "net/http"
|
|
import "strings"
|
|
|
|
type Params = map[string]string
|
|
|
|
type HandlerFunc func(http.ResponseWriter, *http.Request, Params)
|
|
|
|
type route struct {
|
|
method string
|
|
pattern string
|
|
handler HandlerFunc
|
|
}
|
|
|
|
type Router struct {
|
|
routes []route
|
|
}
|
|
|
|
func NewRouter() *Router {
|
|
return &Router{}
|
|
}
|
|
|
|
func (r *Router) Handle(method, pattern string, handler HandlerFunc) {
|
|
var entry route
|
|
entry.method = method
|
|
entry.pattern = pattern
|
|
entry.handler = handler
|
|
r.routes = append(r.routes, entry)
|
|
}
|
|
|
|
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|
var i int
|
|
var rt route
|
|
var params Params
|
|
var ok bool
|
|
for i = 0; i < len(r.routes); i++ {
|
|
rt = r.routes[i]
|
|
if rt.method != req.Method {
|
|
continue
|
|
}
|
|
params, ok = match(rt.pattern, req.URL.Path)
|
|
if !ok {
|
|
continue
|
|
}
|
|
rt.handler(w, req, params)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}
|
|
|
|
func match(pattern, path string) (Params, bool) {
|
|
var pParts []string
|
|
var pathParts []string
|
|
var params Params
|
|
var i int
|
|
var p string
|
|
var seg string
|
|
pParts = split(pattern)
|
|
pathParts = split(path)
|
|
if len(pParts) != len(pathParts) {
|
|
return nil, false
|
|
}
|
|
params = Params{}
|
|
for i = 0; i < len(pParts); i++ {
|
|
p = pParts[i]
|
|
seg = pathParts[i]
|
|
if strings.HasPrefix(p, ":") {
|
|
params[p[1:]] = seg
|
|
continue
|
|
}
|
|
if p != seg {
|
|
return nil, false
|
|
}
|
|
}
|
|
return params, true
|
|
}
|
|
|
|
func split(path string) []string {
|
|
path = strings.Trim(path, "/")
|
|
if path == "" {
|
|
return []string{}
|
|
}
|
|
return strings.Split(path, "/")
|
|
}
|