Files
codit/backend/internal/http/router.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, "/")
}