aboutsummaryrefslogtreecommitdiff
path: root/cmd/server/handlers.go
diff options
context:
space:
mode:
authorMitchell Riedstra <mitch@riedstra.dev>2023-01-06 01:22:38 -0500
committerMitchell Riedstra <mitch@riedstra.dev>2023-01-06 01:27:48 -0500
commit97dd660925434be537cd9a49a1d0c893b223e357 (patch)
tree21d521b08f3a08eb2398a47893eb1543000387b8 /cmd/server/handlers.go
parent1d01acca36b78eeba99da1adb10e72d186433b39 (diff)
downloadgo-website-97dd660925434be537cd9a49a1d0c893b223e357.tar.gz
go-website-97dd660925434be537cd9a49a1d0c893b223e357.tar.xz
Refactor routing and handlers
We were building a new gorilla mux on each connection, change that to an *http.ServeMux and build it once for the lifetime of the application. Tell redis to only cache GET requests.
Diffstat (limited to 'cmd/server/handlers.go')
-rw-r--r--cmd/server/handlers.go185
1 files changed, 95 insertions, 90 deletions
diff --git a/cmd/server/handlers.go b/cmd/server/handlers.go
index d4b7140..3c767a4 100644
--- a/cmd/server/handlers.go
+++ b/cmd/server/handlers.go
@@ -6,129 +6,134 @@ import (
"path/filepath"
"strings"
- "github.com/gorilla/mux"
"riedstra.dev/mitch/go-website/page"
"riedstra.dev/mitch/go-website/rediscache"
)
-func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- rtr := mux.NewRouter()
- rtr.HandleFunc(a.ReIndexPath, a.RebuildIndexHandler)
- rtr.PathPrefix("/static/").Handler(a.StaticHandler())
+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())))
- rtr.HandleFunc("/login", a.LoginHandler)
- rtr.Handle("/logout", a.RequiresLogin(http.HandlerFunc(a.LogoutHandler)))
- rtr.PathPrefix("/edit/").Handler(
- a.RequiresLogin(http.StripPrefix("/edit/", http.HandlerFunc(a.EditPage)))).Methods("GET")
- rtr.PathPrefix("/edit/").Handler(
- a.RequiresLogin(http.StripPrefix("/edit/", http.HandlerFunc(a.SaveEditPage)))).Methods("POST")
-
- if a.redisPool != nil && !a.IsLoggedIn(r) {
- rtr.PathPrefix(fmt.Sprintf("/%s/{tag}", a.FeedPrefix)).Handler(
- rediscache.HandleWithParams(a.redisPool, a.RedisKey,
- http.HandlerFunc(a.FeedHandler)))
-
- rtr.PathPrefix("/_json/").Handler(
- rediscache.HandleWithParams(a.redisPool, a.RedisKey,
- http.StripPrefix("/_json", http.HandlerFunc(a.PageJsonHandler))))
-
- rtr.PathPrefix("/_md/").Handler(
- rediscache.HandleWithParams(a.redisPool, a.RedisKey,
- http.StripPrefix("/_md", http.HandlerFunc(a.PageMarkdownHandler))))
-
- rtr.PathPrefix("/").Handler(rediscache.Handle(
- a.redisPool, a.RedisKey, http.HandlerFunc(a.PageHandler)))
- } else {
- rtr.PathPrefix("/_md/").Handler(http.StripPrefix("/_md",
- http.HandlerFunc(a.PageMarkdownHandler)))
+ return r
+}
- rtr.PathPrefix("/_json/").Handler(http.StripPrefix("/_json",
- http.HandlerFunc(a.PageJsonHandler)))
+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, "/"), "/"))
- rtr.PathPrefix(fmt.Sprintf("/%s/{tag}", a.FeedPrefix)).HandlerFunc(
- a.FeedHandler)
+ routes := map[string]http.Handler{
+ "/_json/": a.PageJsonHandler(),
+ "/_md/": a.PageMarkdownHandler(),
+ a.FeedPrefix: http.StripPrefix(a.FeedPrefix, a.FeedHandler()),
+ "/": a.PageHandler(),
+ }
- rtr.PathPrefix("/").Handler(http.HandlerFunc(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)
+ }
}
- rtr.ServeHTTP(w, r)
+ return r
}
-func (a *App) PageHandler(w http.ResponseWriter, r *http.Request) {
- u := r.URL.Path
- if u == "/" {
- u = "/index"
- }
+func (a *App) Handler() http.Handler {
+ return a.addCacheableRoutes(a.baseRouter())
+}
- loggedIn := a.IsLoggedIn(r)
+func (a *App) PageHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ u := r.URL.Path
+ if u == "/" {
+ u = "/index"
+ }
- if u == "/dashboard" && loggedIn {
- u = page.TemplateDirectory + "/dashboard"
- }
+ loggedIn := a.IsLoggedIn(r)
- // Render nothing inside of the template directory if we're not logged in
- if strings.HasPrefix(u[1:], filepath.Clean(page.TemplateDirectory)) &&
- !loggedIn {
+ if u == "/dashboard" && loggedIn {
+ u = page.TemplateDirectory + "/dashboard"
+ }
- page.Render4xx(w, r, map[string]interface{}{
- "LoggedIn": loggedIn,
- }, 404)
- return
- }
+ // 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)
- u = filepath.Join(".", u)
+ return
+ }
- page.RenderWithVars(w, r, u, map[string]interface{}{
- "LoggedIn": loggedIn,
+ u = filepath.Join(".", u)
+
+ page.RenderWithVars(w, r, u, map[string]interface{}{
+ "LoggedIn": loggedIn,
+ })
})
}
-func (a *App) PageJsonHandler(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
- }
+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)
+ u = filepath.Join(".", u)
- page.RenderJson(w, r, u, map[string]interface{}{}, 200)
+ page.RenderJson(w, r, u, map[string]interface{}{}, 200)
+ })
}
-func (a *App) PageMarkdownHandler(w http.ResponseWriter, r *http.Request) {
- u := r.URL.Path
- if u == "/" {
- u = "/index"
- }
+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
- }
+ // 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)
+ u = filepath.Join(".", u)
- page.RenderMarkdown(w, r, u, map[string]interface{}{}, 200)
+ page.RenderMarkdown(w, r, u, map[string]interface{}{}, 200)
+ })
}
-func (a *App) RebuildIndexHandler(w http.ResponseWriter, r *http.Request) {
- u := r.URL.Path
- if u == "/" {
- u = "/index"
- }
+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)
+ u = filepath.Join(".", u)
- p := page.NewPage("index")
- err := p.RebuildIndex()
+ p := page.NewPage("index")
+ err := p.RebuildIndex()
- page.RenderWithVars(w, r, u, map[string]interface{}{
- "IndexError": err,
+ page.RenderWithVars(w, r, u, map[string]interface{}{
+ "IndexError": err,
+ })
})
}