aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--.golangci.yml2
-rw-r--r--cmd/server/app.go6
-rw-r--r--cmd/server/edit.go168
-rw-r--r--cmd/server/feed.go184
-rw-r--r--cmd/server/handlers.go185
-rw-r--r--cmd/server/main.go2
-rw-r--r--cmd/server/middleware.go136
-rw-r--r--rediscache/main.go6
8 files changed, 363 insertions, 326 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 2201c93..ad60981 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -21,7 +21,7 @@ linters:
- gci
- gochecknoinits
- gocognit
- - goconst
+ # - goconst
- gocritic
- gocyclo
- godot
diff --git a/cmd/server/app.go b/cmd/server/app.go
index d4977ab..9a00628 100644
--- a/cmd/server/app.go
+++ b/cmd/server/app.go
@@ -36,6 +36,10 @@ type App struct {
FeedPrefix string
}
+func newApp() *App {
+ return &App{}
+}
+
func loadConf(fn string) (*App, error) {
fh, err := os.Open(fn)
if err != nil {
@@ -44,7 +48,7 @@ func loadConf(fn string) (*App, error) {
dec := yaml.NewDecoder(fh)
- app := &App{}
+ app := newApp()
err = dec.Decode(app)
if err != nil {
diff --git a/cmd/server/edit.go b/cmd/server/edit.go
index 694028b..10d109a 100644
--- a/cmd/server/edit.go
+++ b/cmd/server/edit.go
@@ -14,88 +14,114 @@ import (
"riedstra.dev/mitch/go-website/page"
)
-func (a *App) EditPage(w http.ResponseWriter, r *http.Request) {
- if r.Method != "GET" {
- page.Render(w, r, page.TemplateDirectory+"/4xx", map[string]interface{}{
- "Title": "Method Not allowed",
- "Description": "Method not allowed",
- "LoggedIn": a.IsLoggedIn(r),
- }, http.StatusMethodNotAllowed)
-
- return
- }
-
- p := r.URL.Path
-
- p = filepath.Clean(p)
-
- fh, err := os.Open("./" + p + page.Suffix)
- if err != nil && errors.Is(err, fs.ErrNotExist) {
- fh, err = os.Open("./" + page.TemplateDirectory +
- "/new-template" + page.Suffix)
- }
-
- if err != nil {
- log.Printf("opening page: %s", err)
- a.Err500Default(w, r)
-
- return
- }
- defer fh.Close()
-
- b, err := io.ReadAll(fh)
- if err != nil {
- log.Printf("opening page: %s", err)
- a.Err500Default(w, r)
-
- return
- }
-
- page.Render(w, r, page.TemplateDirectory+"/edit", map[string]interface{}{
- "Page": p,
- "Content": html.EscapeString(string(b)),
- "LoggedIn": a.IsLoggedIn(r),
- }, http.StatusOK)
+func (a *App) EditPage() http.Handler {
+ getFunc := a.GetEditPage().ServeHTTP
+ postFunc := a.SaveEditPage().ServeHTTP
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch r.Method {
+ case "GET":
+ getFunc(w, r)
+
+ return
+ case "POST":
+ postFunc(w, r)
+
+ return
+ default:
+ a.Err500Default(w, r)
+
+ return
+ }
+ })
}
-func (a *App) SaveEditPage(w http.ResponseWriter, r *http.Request) {
- if r.Method != "POST" {
- a.Err500Default(w, r)
+func (a *App) GetEditPage() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" {
+ page.Render(w, r, page.TemplateDirectory+"/4xx", map[string]interface{}{
+ "Title": "Method Not allowed",
+ "Description": "Method not allowed",
+ "LoggedIn": a.IsLoggedIn(r),
+ }, http.StatusMethodNotAllowed)
+
+ return
+ }
+
+ p := r.URL.Path
+
+ p = filepath.Clean(p)
+
+ fh, err := os.Open("./" + p + page.Suffix)
+ if err != nil && errors.Is(err, fs.ErrNotExist) {
+ fh, err = os.Open("./" + page.TemplateDirectory +
+ "/new-template" + page.Suffix)
+ }
+
+ if err != nil {
+ log.Printf("opening page: %s", err)
+ a.Err500Default(w, r)
+
+ return
+ }
+ defer fh.Close()
+
+ b, err := io.ReadAll(fh)
+ if err != nil {
+ log.Printf("opening page: %s", err)
+ a.Err500Default(w, r)
+
+ return
+ }
+
+ page.Render(w, r, page.TemplateDirectory+"/edit", map[string]interface{}{
+ "Page": p,
+ "Content": html.EscapeString(string(b)),
+ "LoggedIn": a.IsLoggedIn(r),
+ }, http.StatusOK)
+ })
+}
+
+func (a *App) SaveEditPage() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "POST" {
+ a.Err500Default(w, r)
- return
- }
+ return
+ }
- p := r.URL.Path
- content := r.FormValue("content")
+ p := r.URL.Path
+ content := r.FormValue("content")
- content = html.UnescapeString(content)
- p = filepath.Clean(p)
+ content = html.UnescapeString(content)
+ p = filepath.Clean(p)
- fn := "./" + p + page.Suffix
+ fn := "./" + p + page.Suffix
- fh, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- log.Printf("opening file %s for writing: %s", fn, err)
- a.Err500Default(w, r)
+ fh, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ log.Printf("opening file %s for writing: %s", fn, err)
+ a.Err500Default(w, r)
- return
- }
- defer fh.Close()
+ return
+ }
+ defer fh.Close()
- c := bytes.ReplaceAll([]byte(content), []byte{'\r'}, []byte{})
+ c := bytes.ReplaceAll([]byte(content), []byte{'\r'}, []byte{})
- _, err = fh.Write(c)
- if err != nil {
- log.Printf("opening file %s for writing: %s", fn, err)
- a.Err500Default(w, r)
+ _, err = fh.Write(c)
+ if err != nil {
+ log.Printf("opening file %s for writing: %s", fn, err)
+ a.Err500Default(w, r)
- return
- }
+ return
+ }
- http.Redirect(w, r, "/"+r.URL.Path, http.StatusFound)
+ http.Redirect(w, r, "/"+r.URL.Path, http.StatusFound)
- err = a.ClearRedis() // Clear out the cache if any
- if err != nil {
- log.Printf("after editing %s: %s", fn, err)
- }
+ err = a.ClearRedis() // Clear out the cache if any
+ if err != nil {
+ log.Printf("after editing %s: %s", fn, err)
+ }
+ })
}
diff --git a/cmd/server/feed.go b/cmd/server/feed.go
index 212e5da..7e36cb3 100644
--- a/cmd/server/feed.go
+++ b/cmd/server/feed.go
@@ -11,7 +11,6 @@ import (
"strings"
"time"
- "github.com/gorilla/mux"
"riedstra.dev/mitch/go-website/page"
)
@@ -120,128 +119,121 @@ func (a Atom) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
//
// "content" if unset, or set to false content is omitted from the feed
// "limit=n" stop at "n" and return the feed.
-//
-func (a *App) FeedHandler(w http.ResponseWriter, r *http.Request) { //nolint:funlen
- vars := mux.Vars(r)
-
- var (
- addContent bool
- limit int
- )
-
- if _, ok := r.URL.Query()["content"]; ok {
- if r.URL.Query().Get("content") != "false" {
- addContent = true
+func (a *App) FeedHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //nolint:funlen
+ var (
+ addContent bool
+ limit int
+ )
+
+ if _, ok := r.URL.Query()["content"]; ok {
+ if r.URL.Query().Get("content") != "false" {
+ addContent = true
+ }
}
- }
- if l := r.URL.Query().Get("limit"); l != "" {
- i, err := strconv.Atoi(l)
- if err == nil {
- limit = i
+ if l := r.URL.Query().Get("limit"); l != "" {
+ i, err := strconv.Atoi(l)
+ if err == nil {
+ limit = i
+ }
}
- }
-
- tag, ok := vars["tag"]
- if !ok {
- http.Error(w, "Tag not found or supplied", http.StatusNotFound)
-
- return
- }
- p := page.NewPage("index")
+ tag := r.URL.Path
+ p := page.NewPage("index")
- index, err := p.Index()
- if err != nil {
- log.Println(err)
- http.Error(w, "Internal server error", http.StatusInternalServerError)
+ index, err := p.Index()
+ if err != nil {
+ log.Println(err)
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
- return
- }
+ return
+ }
- pages, ok := index[tag]
- if !ok {
- http.Error(w, "Invalid tag", http.StatusNotFound)
+ pages, ok := index[tag]
+ if !ok {
+ http.Error(w, "Invalid tag", http.StatusNotFound)
- return
- }
+ return
+ }
- pages, dateless := pages.RemoveDateless()
- for _, p := range dateless {
- log.Printf("Warning, page %s has no Date field. Skipping inclusion on feed", p)
- }
+ pages, dateless := pages.RemoveDateless()
+ for _, p := range dateless {
+ log.Printf("Warning, page %s has no Date field. Skipping inclusion on feed", p)
+ }
- pages.SortDate()
+ pages.SortDate()
- feed := &Atom{
- Author: a.Author,
- Title: a.Title,
- Id: a.FeedId,
- Updated: &a.Updated.Time,
- Subtitle: a.Description,
- }
+ feed := &Atom{
+ Author: a.Author,
+ Title: a.Title,
+ Id: a.FeedId,
+ Updated: &a.Updated.Time,
+ Subtitle: a.Description,
+ }
- entries := []Entry{}
+ entries := []Entry{}
- for n, p := range pages {
- if limit != 0 && n >= limit {
- break
- }
+ for n, p := range pages {
+ if limit != 0 && n >= limit {
+ break
+ }
- if !p.Published {
- continue
- }
+ if !p.Published {
+ continue
+ }
- content := &bytes.Buffer{}
+ content := &bytes.Buffer{}
- err := p.Render(content)
- if err != nil {
- log.Println(err)
- http.Error(w, "Internal server error", http.StatusInternalServerError)
+ err := p.Render(content)
+ if err != nil {
+ log.Println(err)
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
- return
- }
+ return
+ }
- entry := Entry{
- Title: p.Title(),
- Updated: &p.Date.Time,
- Links: []Link{{Href: strings.Join([]string{a.SiteURL, p.Path()}, "/")}},
- }
+ entry := Entry{
+ Title: p.Title(),
+ Updated: &p.Date.Time,
+ Links: []Link{{Href: strings.Join([]string{a.SiteURL, p.Path()}, "/")}},
+ }
- if p.AuthorName != "" {
- entry.Author = &Author{
- Name: p.AuthorName,
+ if p.AuthorName != "" {
+ entry.Author = &Author{
+ Name: p.AuthorName,
+ }
+ if p.AuthorEmail != "" {
+ entry.Author.Email = p.AuthorEmail
+ }
}
- if p.AuthorEmail != "" {
- entry.Author.Email = p.AuthorEmail
+
+ if addContent {
+ entry.Content = &Content{Type: "html", Data: content.String()}
}
- }
- if addContent {
- entry.Content = &Content{Type: "html", Data: content.String()}
+ entries = append(entries, entry)
}
- entries = append(entries, entry)
- }
-
- feed.Entries = entries
+ feed.Entries = entries
- w.Header().Add("Content-type", "application/xml")
+ w.Header().Add("Content-type", "application/xml")
- _, err = w.Write([]byte(xml.Header))
- if err != nil {
- log.Println("Writing xml: ", err)
+ _, err = w.Write([]byte(xml.Header))
+ if err != nil {
+ log.Println("Writing xml: ", err)
- return
- }
+ return
+ }
- enc := xml.NewEncoder(w)
- enc.Indent("", " ")
+ enc := xml.NewEncoder(w)
+ enc.Indent("", " ")
- err = enc.Encode(feed)
- if err != nil {
- log.Println(err)
- // Headers probably already sent, but we'll try anyway
- http.Error(w, "Internal server error", http.StatusInternalServerError)
- }
+ err = enc.Encode(feed)
+ if err != nil {
+ log.Println(err)
+ // Headers probably already sent, but we'll try anyway
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ }
+ })
}
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,
+ })
})
}
diff --git a/cmd/server/main.go b/cmd/server/main.go
index f4f8dc3..d50c468 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -137,7 +137,7 @@ func main() { //nolint:funlen
page.Funcs["ClearRedis"] = app.ClearRedis
srv := &http.Server{
- Handler: app,
+ Handler: app.Handler(),
Addr: listen,
WriteTimeout: time.Duration(pageTimeout) * time.Second,
ReadTimeout: time.Duration(pageTimeout) * time.Second,
diff --git a/cmd/server/middleware.go b/cmd/server/middleware.go
index 7ba34cf..d0957fd 100644
--- a/cmd/server/middleware.go
+++ b/cmd/server/middleware.go
@@ -25,96 +25,100 @@ func (a *App) Err500Default(w http.ResponseWriter, r *http.Request) {
"Internal server error.")
}
-func (a *App) LogoutHandler(w http.ResponseWriter, r *http.Request) {
- http.SetCookie(w, &http.Cookie{
- Name: "Auth",
- HttpOnly: a.auth.HTTPOnly,
- SameSite: a.auth.SameSiteStrict,
- Secure: a.auth.Secure,
- Value: "logout",
- Expires: time.Now().Add(time.Second), //nolint
+func (a *App) LogoutHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ http.SetCookie(w, &http.Cookie{
+ Name: "Auth",
+ HttpOnly: a.auth.HTTPOnly,
+ SameSite: a.auth.SameSiteStrict,
+ Secure: a.auth.Secure,
+ Value: "logout",
+ Expires: time.Now().Add(time.Second), //nolint
+ })
+
+ http.Redirect(w, r, "/", http.StatusFound)
})
-
- http.Redirect(w, r, "/", http.StatusFound)
}
-func (a *App) LoginHandler(w http.ResponseWriter, r *http.Request) { //nolint
- loggedIn := a.IsLoggedIn(r)
+func (a *App) LoginHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //nolint
+ loggedIn := a.IsLoggedIn(r)
- next, _ := url.Parse(r.URL.Query().Get("next"))
+ next, _ := url.Parse(r.URL.Query().Get("next"))
- if r.Method == "GET" && !loggedIn {
- page.RenderForPath(w, r, "login")
+ if r.Method == "GET" && !loggedIn {
+ page.RenderForPath(w, r, "login")
- return
- }
+ return
+ }
+
+ if r.Method == "GET" && loggedIn {
+ if next.Path != "" {
+ http.Redirect(w, r, next.Path, http.StatusFound)
+
+ return
+ }
- if r.Method == "GET" && loggedIn {
- if next.Path != "" {
- http.Redirect(w, r, next.Path, http.StatusFound)
+ http.Redirect(w, r, "/dashboard", http.StatusFound)
return
}
- http.Redirect(w, r, "/dashboard", http.StatusFound)
+ if r.Method != "POST" {
+ a.Err500Default(w, r)
- return
- }
+ return
+ }
- if r.Method != "POST" {
- a.Err500Default(w, r)
+ username := r.FormValue("username")
+ password := r.FormValue("password")
- return
- }
+ var (
+ err error = nil
+ u *users.SiteUser
+ found = false
+ )
- username := r.FormValue("username")
- password := r.FormValue("password")
+ for _, u = range a.auth.Users {
+ if u.Username == username {
+ err = u.CheckPassword(password)
+ found = true
+ }
+ }
- var (
- err error = nil
- u *users.SiteUser
- found = false
- )
+ if err != nil || !found {
+ page.Render(w, r, "login", map[string]interface{}{
+ "Error": "Invalid username or password",
+ "Username": username,
+ }, http.StatusUnauthorized)
- for _, u = range a.auth.Users {
- if u.Username == username {
- err = u.CheckPassword(password)
- found = true
+ return
}
- }
-
- if err != nil || !found {
- page.Render(w, r, "login", map[string]interface{}{
- "Error": "Invalid username or password",
- "Username": username,
- }, http.StatusUnauthorized)
- return
- }
+ token := jwt.NewWithClaims(jwt.SigningMethodHS512, &jwt.StandardClaims{
+ ExpiresAt: time.Now().Add(
+ time.Hour * time.Duration(a.auth.LoginHours)).Unix(),
+ Id: u.Username,
+ })
- token := jwt.NewWithClaims(jwt.SigningMethodHS512, &jwt.StandardClaims{
- ExpiresAt: time.Now().Add(
- time.Hour * time.Duration(a.auth.LoginHours)).Unix(),
- Id: u.Username,
- })
+ ss, err := token.SignedString([]byte(a.auth.TokenKey))
+ if err != nil {
+ log.Println("login: encountered while setting up JWT: ", err)
+ a.Err500Default(w, r)
- ss, err := token.SignedString([]byte(a.auth.TokenKey))
- if err != nil {
- log.Println("login: encountered while setting up JWT: ", err)
- a.Err500Default(w, r)
+ return
+ }
- return
- }
+ http.SetCookie(w, &http.Cookie{
+ Name: "Auth",
+ HttpOnly: a.auth.HTTPOnly,
+ SameSite: a.auth.SameSiteStrict,
+ Secure: a.auth.Secure,
+ Value: ss,
+ })
- http.SetCookie(w, &http.Cookie{
- Name: "Auth",
- HttpOnly: a.auth.HTTPOnly,
- SameSite: a.auth.SameSiteStrict,
- Secure: a.auth.Secure,
- Value: ss,
+ http.Redirect(w, r, "/login", http.StatusFound)
})
-
- http.Redirect(w, r, "/login", http.StatusFound)
}
func (a *App) IsLoggedIn(r *http.Request) bool {
diff --git a/rediscache/main.go b/rediscache/main.go
index 3cbfdea..b504a24 100644
--- a/rediscache/main.go
+++ b/rediscache/main.go
@@ -97,6 +97,12 @@ func Handle(pool *redis.Pool, key string, next http.Handler) http.Handler {
func handle(pool *redis.Pool, key string, params bool, next http.Handler) http.Handler { //nolint:funlen
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" {
+ next.ServeHTTP(w, r)
+
+ return
+ }
+
client := pool.Get()
defer client.Close()