Skip to content

Latest commit

 

History

History
139 lines (120 loc) · 4.18 KB

File metadata and controls

139 lines (120 loc) · 4.18 KB

6.3 Almacenamiento de sesiones

Introducimos los principios de un manejador de sesiones simple en la sección anterior, y entre otras cosas, definimos una interfaz de almacenamiento de sesión. En esta sección, voy a mostrarte un ejemplo de un motor de sesiones basado en memoria que implementa esa interfaz. Puedes mejorar este a otros mecanísmos de almacenamiento también.

	package memory

	import (
	    "container/list"
	    "github.com/astaxie/session"
	    "sync"
	    "time"
	)

	var pder = &Provider{list: list.New()}

	type SessionStore struct {
	    sid          string                      // identificador único de sesión
	    timeAccessed time.Time                   // último tiempo de acceso
	    value        map[interface{}]interface{} // valor de la sesión accedida
	}

	func (st *SessionStore) Set(key, value interface{}) error {
	    st.value[key] = value
	    pder.SessionUpdate(st.sid)
	    return nil
	}

	func (st *SessionStore) Get(key interface{}) interface{} {
	    pder.SessionUpdate(st.sid)
	    if v, ok := st.value[key]; ok {
	        return v
	    } else {
	        return nil
	    }
	    return nil
	}

	func (st *SessionStore) Delete(key interface{}) error {
	    delete(st.value, key)
	    pder.SessionUpdate(st.sid)
	    return nil
	}

	func (st *SessionStore) SessionID() string {
	    return st.sid
	}

	type Provider struct {
	    lock     sync.Mutex               // bloqueo
	    sessions map[string]*list.Element // guardar en memoria
	    list     *list.List               // recikector de basura
	}

	func (pder *Provider) SessionInit(sid string) (session.Session, error) {
	    pder.lock.Lock()
	    defer pder.lock.Unlock()
	    v := make(map[interface{}]interface{}, 0)
	    newsess := &SessionStore{sid: sid, timeAccessed: time.Now(), value: v}
	    element := pder.list.PushBack(newsess)
	    pder.sessions[sid] = element
	    return newsess, nil
	}

	func (pder *Provider) SessionRead(sid string) (session.Session, error) {
	    if element, ok := pder.sessions[sid]; ok {
	        return element.Value.(*SessionStore), nil
	    } else {
	        sess, err := pder.SessionInit(sid)
	        return sess, err
	    }
	    return nil, nil
	}

	func (pder *Provider) SessionDestroy(sid string) error {
	    if element, ok := pder.sessions[sid]; ok {
	        delete(pder.sessions, sid)
	        pder.list.Remove(element)
	        return nil
	    }
	    return nil
	}

	func (pder *Provider) SessionGC(maxlifetime int64) {
	    pder.lock.Lock()
	    defer pder.lock.Unlock()

	    for {
	        element := pder.list.Back()
	        if element == nil {
	            break
	        }
	        if (element.Value.(*SessionStore).timeAccessed.Unix() + maxlifetime) < time.Now().Unix() {
	            pder.list.Remove(element)
	            delete(pder.sessions, element.Value.(*SessionStore).sid)
	        } else {
	            break
	        }
	    }
	}

	func (pder *Provider) SessionUpdate(sid string) error {
	    pder.lock.Lock()
	    defer pder.lock.Unlock()
	    if element, ok := pder.sessions[sid]; ok {
	        element.Value.(*SessionStore).timeAccessed = time.Now()
	        pder.list.MoveToFront(element)
	        return nil
	    }
	    return nil
	}

	func init() {
	    pder.sessions = make(map[string]*list.Element, 0)
	    session.Register("memory", pder)
	}

El ejmplo superior implementa un mecanismo de almacenamiento de sesiones en memoria. Usa la función init() para registrar este motor de almacenamiento al manejador de sesiones. ¿Cómo registramos este motor en nuestro programa principal?

	import (
	    "github.com/astaxie/session"
	    _ "github.com/astaxie/session/providers/memory"
	)

Usamos el mecanismo de importación del guión bajo (que invoca a la funcuón init del paquete automáticamente) para registrar este motor al manejador de sesiones. Luego usamos el siguiente código para inicializar el manejador de sesión.

	var globalSessions *session.Manager

	// initialize in init() function
	func init() {
	    globalSessions, _ = session.NewManager("memory", "gosessionid", 3600)
	    go globalSessions.GC()
	}

Enlaces