package wrouter import ( "fmt" "net/http" "strings" "git.aiterp.net/gisle/notebook3/session" "git.aiterp.net/gisle/wrouter/auth" ) type Route interface { Handle(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool } type Router struct { paths map[Route]string routes []Route } func (router *Router) Route(path string, route Route) { if router.paths == nil { router.paths = make(map[Route]string, 16) } router.paths[route] = path router.routes = append(router.routes, route) } func (router *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() // Allow REST for clients of yore if req.Header.Get("X-Method") != "" { req.Method = strings.ToUpper(req.Header.Get("X-Method")) } // Resolve session cookies var user *auth.User cookie, err := req.Cookie(session.CookieName) if cookie != nil && err == nil { sess := auth.FindSession(cookie.Value) if sess != nil { user = auth.FindUser(sess.UserID) } } for index, route := range router.routes { path := router.paths[route] if strings.HasPrefix(strings.ToLower(req.URL.Path), path) { // Just so the handler can replace the path properly in case of case // insensitive clients getting fancy on it. path = req.URL.Path[:len(path)] // Attach a little something for testing w.Header().Set("X-Route-Path", path) w.Header().Set("X-Route-Index", fmt.Sprint(index)) if route.Handle(path, w, req, user) { return } } } w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.WriteHeader(404) } func (router *Router) Listen(host string, port int) error { return http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), router) }