/* * @Author: Bartuccio Antoine * @Date: 2018-07-16 14:07:07 * @Last Modified by: klmp200 * @Last Modified time: 2018-07-18 00:03:26 */ package gowebframework import ( "fmt" "github.com/google/uuid" "log" "net/http" "net/url" "sync" "time" ) var SESSION *SessionManager var providers = make(map[string]Provider) type SessionManager struct { cookieName string // Name of the cookie on the client side lock sync.Mutex provider Provider maxLifetime time.Duration } type Session interface { Set(key string, value interface{}) error // set a session value Get(key string) interface{} // get session value Delete(key string) error // delete session value SessionUUID() string // get the current session UUID } type Provider interface { SessionInit(uuid string) (Session, error) SessionRead(uuid string) (Session, error) SessionDestroy(uuid string) error SessionClearExpired(maxLifetime time.Duration) } func (manager *SessionManager) generateUUID() string { return uuid.New().String() } // Launch a Clear Expired Sessions task at fixed rate func clearExpiredSessionsCron() { SESSION.lock.Lock() lifetime := SESSION.maxLifetime SESSION.lock.Unlock() for { SESSION.lock.Lock() SESSION.provider.SessionClearExpired(lifetime) SESSION.lock.Unlock() time.Sleep(lifetime) } } func SessionProviderRegister(provider Provider, providerName string) error { if provider == nil { return fmt.Errorf("No provider found for provider name %s", providerName) } if _, exists := providers[providerName]; exists { return fmt.Errorf("Provider with name %s already exists", providerName) } providers[providerName] = provider return nil } func (manager *SessionManager) GetSession(w http.ResponseWriter, r *http.Request) Session { var session Session manager.lock.Lock() defer manager.lock.Unlock() cookie, err := r.Cookie(manager.cookieName) if err != nil || cookie.Value == "" { // Create a new session session_id := manager.generateUUID() s, err := manager.provider.SessionInit(session_id) if err != nil { log.Fatal(err) } session = s AddCookie(w, manager.cookieName, url.QueryEscape(session_id), manager.maxLifetime) } else { // Get the session session_id, _ := url.QueryUnescape(cookie.Value) s, err := manager.provider.SessionRead(session_id) if err != nil { log.Fatal(err) } session = s } return session } func newSessionManager(providerName string, cookieName string, maxLifetime time.Duration) (*SessionManager, error) { provider, ok := providers[providerName] if !ok { return nil, fmt.Errorf("Session error: unknown provider %s", providerName) } return &SessionManager{provider: provider, cookieName: cookieName, maxLifetime: maxLifetime}, nil }