package main import ( "fmt" "net/http" "path/filepath" "strings" "riedstra.dev/mitch/go-website/page" "riedstra.dev/mitch/go-website/rediscache" ) func (a *App) baseRouter() *http.ServeMux { r := http.NewServeMux() r.Handle(a.ReIndexPath, a.RebuildIndexHandler()) r.Handle("/static/", a.StaticHandler()) r.Handle("/login", a.LoginHandler()) r.Handle("/logout", a.RequiresLogin(a.LogoutHandler())) r.Handle("/edit/", a.RequiresLogin( http.StripPrefix("/edit/", a.EditPage()))) return r } func (a *App) addCacheableRoutes(r *http.ServeMux) *http.ServeMux { // make sure it always has a trailing slash and starts with a slash a.FeedPrefix = fmt.Sprintf("/%s/", strings.TrimSuffix(strings.TrimPrefix(a.FeedPrefix, "/"), "/")) routes := map[string]http.Handler{ "/_json/": a.PageJsonHandler(), "/_md/": a.PageMarkdownHandler(), a.FeedPrefix: http.StripPrefix(a.FeedPrefix, a.FeedHandler()), "/": a.PageHandler(), } for route, handler := range routes { if a.redisPool != nil { r.Handle(route, rediscache.Handle(a.redisPool, a.RedisKey, handler)) } else { r.Handle(route, handler) } } return r } func (a *App) Handler() http.Handler { return a.addCacheableRoutes(a.baseRouter()) } func (a *App) PageHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { u := r.URL.Path if u == "/" { u = "/index" } loggedIn := a.IsLoggedIn(r) if u == "/dashboard" && loggedIn { u = page.TemplateDirectory + "/dashboard" } // Render nothing inside of the template directory if we're not logged in if strings.HasPrefix(u[1:], filepath.Clean(page.TemplateDirectory)) && !loggedIn { page.Render4xx(w, r, map[string]interface{}{ "LoggedIn": loggedIn, }, 404) return } u = filepath.Join(".", u) page.RenderWithVars(w, r, u, map[string]interface{}{ "LoggedIn": loggedIn, }) }) } func (a *App) PageJsonHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { u := r.URL.Path if u == "/" { u = "/index" } // Skip template directory if strings.HasPrefix(u[1:], filepath.Clean(page.TemplateDirectory)) { page.Render4xx(w, r, map[string]interface{}{}, 404) return } u = filepath.Join(".", u) page.RenderJson(w, r, u, map[string]interface{}{}, 200) }) } func (a *App) PageMarkdownHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { u := r.URL.Path if u == "/" { u = "/index" } // Skip template directory if strings.HasPrefix(u[1:], filepath.Clean(page.TemplateDirectory)) { page.Render4xx(w, r, map[string]interface{}{}, 404) return } u = filepath.Join(".", u) page.RenderMarkdown(w, r, u, map[string]interface{}{}, 200) }) } func (a *App) RebuildIndexHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { u := r.URL.Path if u == "/" { u = "/index" } u = filepath.Join(".", u) p := page.NewPage("index") err := p.RebuildIndex() page.RenderWithVars(w, r, u, map[string]interface{}{ "IndexError": err, }) }) } // StaticHandler simply returns a HTTP handler that looks at the current // directory and exposes `static` via HTTP `/static`. func (a *App) StaticHandler() http.Handler { return http.StripPrefix("/static/", http.FileServer(http.Dir(a.StaticDirectory))) }