diff --git a/session/sess_file.go b/session/sess_file.go index 38e52af8..016a30f5 100644 --- a/session/sess_file.go +++ b/session/sess_file.go @@ -28,7 +28,6 @@ func (fs *FileSessionStore) Set(key, value interface{}) error { fs.lock.Lock() defer fs.lock.Unlock() fs.values[key] = value - fs.updatecontent() return nil } @@ -47,7 +46,6 @@ func (fs *FileSessionStore) Delete(key interface{}) error { fs.lock.Lock() defer fs.lock.Unlock() delete(fs.values, key) - fs.updatecontent() return nil } @@ -55,7 +53,6 @@ func (fs *FileSessionStore) Flush() error { fs.lock.Lock() defer fs.lock.Unlock() fs.values = make(map[interface{}]interface{}) - fs.updatecontent() return nil } @@ -64,10 +61,7 @@ func (fs *FileSessionStore) SessionID() string { } func (fs *FileSessionStore) SessionRelease() { - fs.f.Close() -} - -func (fs *FileSessionStore) updatecontent() { + defer fs.f.Close() b, err := encodeGob(fs.values) if err != nil { return diff --git a/session/sess_mysql.go b/session/sess_mysql.go index 9eff85ef..6d938aee 100644 --- a/session/sess_mysql.go +++ b/session/sess_mysql.go @@ -27,7 +27,6 @@ func (st *MysqlSessionStore) Set(key, value interface{}) error { st.lock.Lock() defer st.lock.Unlock() st.values[key] = value - st.updatemysql() return nil } @@ -46,7 +45,6 @@ func (st *MysqlSessionStore) Delete(key interface{}) error { st.lock.Lock() defer st.lock.Unlock() delete(st.values, key) - st.updatemysql() return nil } @@ -54,7 +52,6 @@ func (st *MysqlSessionStore) Flush() error { st.lock.Lock() defer st.lock.Unlock() st.values = make(map[interface{}]interface{}) - st.updatemysql() return nil } @@ -62,7 +59,8 @@ func (st *MysqlSessionStore) SessionID() string { return st.sid } -func (st *MysqlSessionStore) updatemysql() { +func (st *MysqlSessionStore) SessionRelease() { + defer st.c.Close() if len(st.values) > 0 { b, err := encodeGob(st.values) if err != nil { @@ -72,10 +70,6 @@ func (st *MysqlSessionStore) updatemysql() { } } -func (st *MysqlSessionStore) SessionRelease() { - st.c.Close() -} - type MysqlProvider struct { maxlifetime int64 savePath string diff --git a/session/sess_redis.go b/session/sess_redis.go index b8cde175..665d62eb 100644 --- a/session/sess_redis.go +++ b/session/sess_redis.go @@ -4,6 +4,7 @@ import ( "github.com/garyburd/redigo/redis" "strconv" "strings" + "sync" ) var redispder = &RedisProvider{} @@ -13,33 +14,42 @@ var MAX_POOL_SIZE = 100 var redisPool chan redis.Conn type RedisSessionStore struct { - c redis.Conn - sid string + c redis.Conn + sid string + lock sync.RWMutex + values map[interface{}]interface{} } func (rs *RedisSessionStore) Set(key, value interface{}) error { - //_, err := rs.c.Do("HSET", rs.sid, key, value) - _, err := rs.c.Do("HSET", rs.sid, key, value) - return err + rs.lock.Lock() + defer rs.lock.Unlock() + rs.values[key] = value + return nil } func (rs *RedisSessionStore) Get(key interface{}) interface{} { - reply, err := rs.c.Do("HGET", rs.sid, key) - if err != nil { + rs.lock.RLock() + defer rs.lock.RUnlock() + if v, ok := rs.values[key]; ok { + return v + } else { return nil } - return reply + return nil } func (rs *RedisSessionStore) Delete(key interface{}) error { - //_, err := rs.c.Do("HDEL", rs.sid, key) - _, err := rs.c.Do("HDEL", rs.sid, key) - return err + rs.lock.Lock() + defer rs.lock.Unlock() + delete(rs.values, key) + return nil } func (rs *RedisSessionStore) Flush() error { - _, err := rs.c.Do("DEL", rs.sid) - return err + rs.lock.Lock() + defer rs.lock.Unlock() + rs.values = make(map[interface{}]interface{}) + return nil } func (rs *RedisSessionStore) SessionID() string { @@ -47,7 +57,23 @@ func (rs *RedisSessionStore) SessionID() string { } func (rs *RedisSessionStore) SessionRelease() { - rs.c.Close() + defer rs.c.Close() + keys, err := redis.Values(rs.c.Do("HKEYS", rs.sid)) + if err == nil { + for _, key := range keys { + if val, ok := rs.values[key]; ok { + rs.c.Do("HSET", rs.sid, key, val) + rs.Delete(key) + } else { + rs.c.Do("HDEL", rs.sid, key) + } + } + } + if len(rs.values) > 0 { + for k, v := range rs.values { + rs.c.Do("HSET", rs.sid, k, v) + } + } } type RedisProvider struct { @@ -103,7 +129,19 @@ func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) { c.Do("HSET", sid, sid, rp.maxlifetime) } c.Do("EXPIRE", sid, rp.maxlifetime) - rs := &RedisSessionStore{c: c, sid: sid} + kvs, err := redis.Values(c.Do("HGETALL", sid)) + vals := make(map[interface{}]interface{}) + var key interface{} + if err == nil { + for k, v := range kvs { + if k%2 == 0 { + key = v + } else { + vals[key] = v + } + } + } + rs := &RedisSessionStore{c: c, sid: sid, values: vals} return rs, nil } @@ -114,7 +152,19 @@ func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er } c.Do("RENAME", oldsid, sid) c.Do("EXPIRE", sid, rp.maxlifetime) - rs := &RedisSessionStore{c: c, sid: sid} + kvs, err := redis.Values(c.Do("HGETALL", sid)) + vals := make(map[interface{}]interface{}) + var key interface{} + if err == nil { + for k, v := range kvs { + if k%2 == 0 { + key = v + } else { + vals[key] = v + } + } + } + rs := &RedisSessionStore{c: c, sid: sid, values: vals} return rs, nil } diff --git a/session/session.go b/session/session.go index 9e795ee7..5db9bd8b 100644 --- a/session/session.go +++ b/session/session.go @@ -18,7 +18,7 @@ type SessionStore interface { Get(key interface{}) interface{} //get session value Delete(key interface{}) error //delete session value SessionID() string //back current sessionID - SessionRelease() // release the resource + SessionRelease() // release the resource & save data to provider Flush() error //delete all data } @@ -129,17 +129,9 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se if manager.maxage >= 0 { cookie.MaxAge = manager.maxage } - //cookie.Expires = time.Now().Add(time.Duration(manager.maxlifetime) * time.Second) http.SetCookie(w, cookie) r.AddCookie(cookie) } else { - //cookie.Expires = time.Now().Add(time.Duration(manager.maxlifetime) * time.Second) - //cookie.HttpOnly = true - //cookie.Path = "/" - //if manager.maxage >= 0 { - // cookie.MaxAge = manager.maxage - // http.SetCookie(w, cookie) - //} sid, _ := url.QueryUnescape(cookie.Value) session, _ = manager.provider.SessionRead(sid) } @@ -200,8 +192,16 @@ func (manager *Manager) GetActiveSession() int { return manager.provider.SessionAll() } -//remote_addr cruunixnano randdata +func (manager *Manager) SetHashFunc(hasfunc, hashkey string) { + manager.hashfunc = hasfunc + manager.hashkey = hashkey +} +func (manager *Manager) SetSecure(secure bool) { + manager.secure = secure +} + +//remote_addr cruunixnano randdata func (manager *Manager) sessionId(r *http.Request) (sid string) { bs := make([]byte, 24) if _, err := io.ReadFull(rand.Reader, bs); err != nil {