// Package middleware to deal with sessions package middleware import ( "context" "crypto/rand" "fmt" "net/http" ) type Session struct { User string } type SessionStore struct { sessions map[string]Session } type ContextKey string func NewSessionStore() SessionStore { return SessionStore{sessions: make(map[string]Session, 10)} } func (s *SessionStore) Login(user string, w http.ResponseWriter) { sessionID := rand.Text() s.sessions[sessionID] = Session{User: user} cookie := http.Cookie{ Name: "id", Value: sessionID, MaxAge: 3600, Secure: true, HttpOnly: true, Path: "/", } http.SetCookie(w, &cookie) } func (s *SessionStore) Logout(w http.ResponseWriter, r *http.Request) { session := r.Context().Value(ContextKey("session")).(string) delete(s.sessions, session) cookie := http.Cookie{ Name: "id", Value: "", MaxAge: -1, Secure: true, HttpOnly: true, Path: "/", } http.SetCookie(w, &cookie) } func (s *SessionStore) AsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sessionCookie, err := r.Cookie("id") for name, values := range r.Header { for _, value := range values { fmt.Println(name, value) } } // No session yet if err != nil { http.Redirect(w, r, "/login/", http.StatusFound) return } session, ok := s.sessions[sessionCookie.Value] // Session expired if !ok { http.Redirect(w, r, "/login/", http.StatusFound) return } ctx := r.Context() ctx = context.WithValue( context.WithValue( ctx, ContextKey("user"), session.User, ), ContextKey("session"), sessionCookie.Value, ) next.ServeHTTP(w, r.WithContext(ctx)) }) }