From 90bf997578b3bf43012a04a0e814e5dab506ec61 Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Tue, 18 Feb 2025 21:37:15 +1100 Subject: [PATCH] Added 503 error page and streamlined error paging --- handlers/errorpage.go | 24 ++++++++++++++++++++++++ handlers/index.go | 6 +----- handlers/login.go | 2 +- jwt/revoke.go | 1 - middleware/authentication.go | 11 ++++++----- middleware/logging.go | 3 ++- middleware/pageprotection.go | 9 ++------- view/page/error.templ | 5 +++-- 8 files changed, 39 insertions(+), 22 deletions(-) create mode 100644 handlers/errorpage.go diff --git a/handlers/errorpage.go b/handlers/errorpage.go new file mode 100644 index 0000000..8f04001 --- /dev/null +++ b/handlers/errorpage.go @@ -0,0 +1,24 @@ +package handlers + +import ( + "net/http" + "projectreshoot/view/page" +) + +func ErrorPage( + errorCode int, + w http.ResponseWriter, + r *http.Request, +) { + message := map[int]string{ + 401: "You need to login to view this page.", + 403: "You do not have permission to view this page.", + 404: "The page or resource you have requested does not exist.", + 500: `An error occured on the server. Please try again, and if this + continues to happen contact an administrator.`, + 503: "The server is currently down for maintenance and should be back soon. =)", + } + w.WriteHeader(http.StatusUnauthorized) + page.Error(errorCode, http.StatusText(errorCode), message[errorCode]). + Render(r.Context(), w) +} diff --git a/handlers/index.go b/handlers/index.go index 974b5be..4c22dc6 100644 --- a/handlers/index.go +++ b/handlers/index.go @@ -12,11 +12,7 @@ func HandleRoot() http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { - page.Error( - "404", - "Page not found", - "The page or resource you have requested does not exist", - ).Render(r.Context(), w) + ErrorPage(http.StatusNotFound, w, r) return } page.Index().Render(r.Context(), w) diff --git a/handlers/login.go b/handlers/login.go index b646e7e..0acef1b 100644 --- a/handlers/login.go +++ b/handlers/login.go @@ -56,7 +56,7 @@ func HandleLoginRequest( ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { - ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second) + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) defer cancel() // Start the transaction diff --git a/jwt/revoke.go b/jwt/revoke.go index e988a4e..016f33e 100644 --- a/jwt/revoke.go +++ b/jwt/revoke.go @@ -27,7 +27,6 @@ func CheckTokenNotRevoked(ctx context.Context, tx *db.SafeTX, t Token) (bool, er if err != nil { return false, errors.Wrap(err, "tx.Query") } - // NOTE: rows.Close() defer rows.Close() revoked := rows.Next() return !revoked, nil diff --git a/middleware/authentication.go b/middleware/authentication.go index 92837e5..fc2125d 100644 --- a/middleware/authentication.go +++ b/middleware/authentication.go @@ -10,6 +10,7 @@ import ( "projectreshoot/contexts" "projectreshoot/cookies" "projectreshoot/db" + "projectreshoot/handlers" "projectreshoot/jwt" "github.com/pkg/errors" @@ -106,7 +107,7 @@ func Authentication( next.ServeHTTP(w, r) return } - ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second) + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) defer cancel() if atomic.LoadUint32(maint) == 1 { cancel() @@ -115,10 +116,10 @@ func Authentication( // Start the transaction tx, err := conn.Begin(ctx) if err != nil { - // Failed to start transaction, send 503 code to client - logger.Warn().Err(err).Msg("Skipping Auth - unable to start a transaction") - w.WriteHeader(http.StatusServiceUnavailable) - next.ServeHTTP(w, r) + // Failed to start transaction, skip auth + logger.Warn().Err(err). + Msg("Skipping Auth - unable to start a transaction") + handlers.ErrorPage(http.StatusServiceUnavailable, w, r) return } user, err := getAuthenticatedUser(config, ctx, tx, w, r) diff --git a/middleware/logging.go b/middleware/logging.go index de42258..fe9caf2 100644 --- a/middleware/logging.go +++ b/middleware/logging.go @@ -3,6 +3,7 @@ package middleware import ( "net/http" "projectreshoot/contexts" + "projectreshoot/handlers" "time" "github.com/rs/zerolog" @@ -30,7 +31,7 @@ func Logging(logger *zerolog.Logger, next http.Handler) http.Handler { } start, err := contexts.GetStartTime(r.Context()) if err != nil { - // TODO: Handle failure here. internal server error maybe + handlers.ErrorPage(http.StatusInternalServerError, w, r) return } wrapped := &wrappedWriter{ diff --git a/middleware/pageprotection.go b/middleware/pageprotection.go index f5537b2..3a5c14e 100644 --- a/middleware/pageprotection.go +++ b/middleware/pageprotection.go @@ -3,7 +3,7 @@ package middleware import ( "net/http" "projectreshoot/contexts" - "projectreshoot/view/page" + "projectreshoot/handlers" ) // Checks if the user is set in the context and shows 401 page if not logged in @@ -11,12 +11,7 @@ func RequiresLogin(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user := contexts.GetUser(r.Context()) if user == nil { - w.WriteHeader(http.StatusUnauthorized) - page.Error( - "401", - "Unauthorized", - "Please login to view this page", - ).Render(r.Context(), w) + handlers.ErrorPage(http.StatusUnauthorized, w, r) return } next.ServeHTTP(w, r) diff --git a/view/page/error.templ b/view/page/error.templ index dd35f84..2ec5095 100644 --- a/view/page/error.templ +++ b/view/page/error.templ @@ -1,11 +1,12 @@ package page import "projectreshoot/view/layout" +import "strconv" // Page template for Error pages. Error code should be a HTTP status code as // a string, and err should be the corresponding response title. // Message is a custom error message displayed below the code and error. -templ Error(code string, err string, message string) { +templ Error(code int, err string, message string) { @layout.Global() {

{ code }

+ >{ strconv.Itoa(code) }