package app import ( "context" "log" "net/http" "time" ) type ctxKey string const userKey ctxKey = "user" func (a *App) withAuth(next func(http.ResponseWriter, *http.Request, User)) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var u User if a.cfg.DevMode { u = User{Username: a.cfg.DemoUser, Email: a.cfg.DemoEmail} } else { u = User{Username: r.Header.Get(a.cfg.AuthHeaderUser), Email: r.Header.Get(a.cfg.AuthHeaderEmail)} if u.Username == "" { http.Error(w, "missing authenticated user header", http.StatusUnauthorized) return } } next(w, r.WithContext(context.WithValue(r.Context(), userKey, u)), u) } } func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() lrw := &logResponseWriter{ResponseWriter: w, status: http.StatusOK} next.ServeHTTP(lrw, r) log.Printf("method=%s path=%s status=%d bytes=%d dur_ms=%d remote=%s ua=%q", r.Method, r.URL.Path, lrw.status, lrw.bytes, time.Since(start).Milliseconds(), r.RemoteAddr, r.UserAgent(), ) }) } type logResponseWriter struct { http.ResponseWriter status int bytes int } func (l *logResponseWriter) WriteHeader(statusCode int) { l.status = statusCode l.ResponseWriter.WriteHeader(statusCode) } func (l *logResponseWriter) Write(b []byte) (int, error) { n, err := l.ResponseWriter.Write(b) l.bytes += n return n, err }