package main import ( "crypto/rand" "encoding/hex" "net/http" "sync" "time" ) type sessionInfo struct { last time.Time } var ( sessionMu sync.Mutex sessions = make(map[string]*sessionInfo) ) const ( idleTimeout = 5 * time.Minute gcPeriod = 1 * time.Hour ) func WebCreateSession() string { buf := make([]byte, 32) rand.Read(buf) return hex.EncodeToString(buf) } func WebAddSession(id string) { sessionMu.Lock() sessions[id] = &sessionInfo{last: time.Now()} sessionMu.Unlock() } func WebHasSession(id string) bool { now := time.Now() sessionMu.Lock() defer sessionMu.Unlock() s, ok := sessions[id] if !ok { return false } if now.Sub(s.last) > idleTimeout { delete(sessions, id) return false } s.last = now return true } func WebCheckSession(r *http.Request) bool { c, err := r.Cookie("session_id") if err != nil { return false } return WebHasSession(c.Value) } func StartSessionCleaner() { go func() { ticker := time.NewTicker(gcPeriod) defer ticker.Stop() for range ticker.C { now := time.Now() sessionMu.Lock() for k, s := range sessions { if now.Sub(s.last) > idleTimeout { delete(sessions, k) } } sessionMu.Unlock() } }() }