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, "/") }