|
|
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 var sess *auth.Session 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) { if user != nil && user.LoggedOut() { auth.CloseSession(sess.ID) }
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) }
|