HN-like selfhosted forums

Code git clone ssh://git.poy.ooo:6969/~rii/district ZIP
app/middleware.go / 2KiB #f41e3781
Raw
package appimport (	"context"	"log"	"net/http"	"slices"	"time")type contextKey struct{}var (	sessionKey contextKey)type Middleware func(http.Handler) http.Handlerfunc Chain(h http.Handler, mws ...Middleware) http.Handler {	for _, mw := range slices.Backward(mws) {		h = mw(h)	}	return h}type logResponseWriter struct {	http.ResponseWriter	statusCode int}func (rw *logResponseWriter) WriteHeader(code int) {	rw.statusCode = code	rw.ResponseWriter.WriteHeader(code)}func (ro *Router) Logging(next http.Handler) http.Handler {	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {		start := time.Now()		rw := &logResponseWriter{			ResponseWriter: w,			statusCode:     http.StatusOK, // go defaults to 200 OK		}		next.ServeHTTP(rw, r)		elapsed := time.Since(start)		log.Printf("%d %s %s %s", rw.statusCode, elapsed, r.Method, r.URL.Path)	})}// Authentication is a middleware that injects an AuthSession into the request contextfunc (ro *Router) Authentication(next http.Handler) http.Handler {	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {		cookie, err := r.Cookie("district_session")		if err != nil {			next.ServeHTTP(w, r)			return		}		se, err := ro.auth.GetSession(r.Context(), cookie.Value)		if err != nil {			next.ServeHTTP(w, r)			return		}		ctx := context.WithValue(r.Context(), sessionKey, se)		next.ServeHTTP(w, r.WithContext(ctx))	})}// RequireAuthRedirect is a middleware that redirects anonymous users to the login page// Useful for browser facing GET and non mutating requests.func (ro *Router) RequireAuthRedirect(next http.Handler) http.Handler {	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {		_, ok := SessionFromContext(r.Context())		if !ok {			http.Redirect(w, r, "/login", http.StatusSeeOther)			return		}		next.ServeHTTP(w, r)	})}// RequireAuth is a middleware that returns 401 Unauthorized for anonymous requests.// Useful for POST on forms, PUT and PATCH requests.func (ro *Router) RequireAuth(next http.Handler) http.Handler {	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {		_, ok := SessionFromContext(r.Context())		if !ok {			http.Error(w, "unauthorized", http.StatusUnauthorized)			return		}		next.ServeHTTP(w, r)	})}