1
0
mirror of https://github.com/astaxie/beego.git synced 2024-12-24 13:40:49 +00:00
Beego/session/redis/sess_redis.go

227 lines
4.9 KiB
Go
Raw Normal View History

2014-04-12 05:18:18 +00:00
// Beego (http://beego.me/)
// @description beego is an open-source, high-performance web framework for the Go programming language.
// @link http://github.com/astaxie/beego for the canonical source repository
// @license http://github.com/astaxie/beego/blob/master/LICENSE
// @authors astaxie
package session
import (
2014-01-05 06:48:36 +00:00
"net/http"
2013-10-28 14:19:37 +00:00
"strconv"
"strings"
2013-11-05 13:59:35 +00:00
"sync"
2013-12-03 13:37:39 +00:00
"github.com/astaxie/beego/session"
2013-12-03 13:37:39 +00:00
"github.com/beego/redigo/redis"
)
var redispder = &RedisProvider{}
// redis max pool size
2013-10-28 14:19:37 +00:00
var MAX_POOL_SIZE = 100
2013-05-14 15:55:50 +00:00
var redisPool chan redis.Conn
// redis session store
type RedisSessionStore struct {
2014-01-21 10:48:16 +00:00
p *redis.Pool
2013-12-14 15:29:17 +00:00
sid string
lock sync.RWMutex
values map[interface{}]interface{}
maxlifetime int64
}
// set value in redis session
func (rs *RedisSessionStore) Set(key, value interface{}) error {
2013-11-05 13:59:35 +00:00
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values[key] = value
return nil
}
// get value in redis session
func (rs *RedisSessionStore) Get(key interface{}) interface{} {
2013-11-05 13:59:35 +00:00
rs.lock.RLock()
defer rs.lock.RUnlock()
if v, ok := rs.values[key]; ok {
return v
} else {
return nil
}
}
// delete value in redis session
func (rs *RedisSessionStore) Delete(key interface{}) error {
2013-11-05 13:59:35 +00:00
rs.lock.Lock()
defer rs.lock.Unlock()
delete(rs.values, key)
return nil
}
// clear all values in redis session
2013-09-26 10:07:00 +00:00
func (rs *RedisSessionStore) Flush() error {
2013-11-05 13:59:35 +00:00
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values = make(map[interface{}]interface{})
return nil
2013-09-26 10:07:00 +00:00
}
// get redis session id
func (rs *RedisSessionStore) SessionID() string {
return rs.sid
}
// save session values to redis
2014-01-05 06:48:36 +00:00
func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
c := rs.p.Get()
defer c.Close()
// if rs.values is empty, return directly
if len(rs.values) < 1 {
c.Do("DEL", rs.sid)
return
}
b, err := session.EncodeGob(rs.values)
if err != nil {
return
2013-11-05 13:59:35 +00:00
}
2014-01-21 10:48:16 +00:00
c.Do("SET", rs.sid, string(b), "EX", rs.maxlifetime)
}
// redis session provider
type RedisProvider struct {
maxlifetime int64
savePath string
2013-10-28 14:19:37 +00:00
poolsize int
password string
poollist *redis.Pool
}
// init redis session
// savepath like redis server addr,pool size,password
// e.g. 127.0.0.1:6379,100,astaxie
2013-10-28 14:19:37 +00:00
func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
rp.maxlifetime = maxlifetime
configs := strings.Split(savePath, ",")
if len(configs) > 0 {
rp.savePath = configs[0]
}
2013-10-28 14:19:37 +00:00
if len(configs) > 1 {
poolsize, err := strconv.Atoi(configs[1])
if err != nil || poolsize <= 0 {
rp.poolsize = MAX_POOL_SIZE
} else {
rp.poolsize = poolsize
}
} else {
rp.poolsize = MAX_POOL_SIZE
2013-05-14 15:55:50 +00:00
}
2013-10-28 14:19:37 +00:00
if len(configs) > 2 {
rp.password = configs[2]
2013-05-14 15:55:50 +00:00
}
2013-10-28 14:19:37 +00:00
rp.poollist = redis.NewPool(func() (redis.Conn, error) {
c, err := redis.Dial("tcp", rp.savePath)
if err != nil {
return nil, err
}
if rp.password != "" {
if _, err := c.Do("AUTH", rp.password); err != nil {
c.Close()
return nil, err
}
}
return c, err
}, rp.poolsize)
return rp.poollist.Get().Err()
}
// read redis session by sid
func (rp *RedisProvider) SessionRead(sid string) (session.SessionStore, error) {
2013-10-28 14:19:37 +00:00
c := rp.poollist.Get()
2014-01-21 10:48:16 +00:00
defer c.Close()
2013-11-05 15:41:01 +00:00
kvs, err := redis.String(c.Do("GET", sid))
var kv map[interface{}]interface{}
if len(kvs) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = session.DecodeGob([]byte(kvs))
2013-11-05 15:41:01 +00:00
if err != nil {
return nil, err
2013-11-05 13:59:35 +00:00
}
}
2014-01-21 10:48:16 +00:00
rs := &RedisSessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
return rs, nil
}
// check redis session exist by sid
2013-11-05 14:23:48 +00:00
func (rp *RedisProvider) SessionExist(sid string) bool {
c := rp.poollist.Get()
2013-12-14 15:29:17 +00:00
defer c.Close()
2014-01-21 10:48:16 +00:00
2013-11-05 15:41:01 +00:00
if existed, err := redis.Int(c.Do("EXISTS", sid)); err != nil || existed == 0 {
2013-11-05 14:23:48 +00:00
return false
} else {
return true
}
}
// generate new sid for redis session
func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
2013-10-28 14:19:37 +00:00
c := rp.poollist.Get()
2014-01-21 10:48:16 +00:00
defer c.Close()
if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); existed == 0 {
// oldsid doesn't exists, set the new sid directly
// ignore error here, since if it return error
// the existed value will be 0
c.Do("SET", sid, "", "EX", rp.maxlifetime)
} else {
c.Do("RENAME", oldsid, sid)
c.Do("EXPIRE", sid, rp.maxlifetime)
}
2014-01-21 10:48:16 +00:00
2013-11-05 15:41:01 +00:00
kvs, err := redis.String(c.Do("GET", sid))
var kv map[interface{}]interface{}
if len(kvs) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = session.DecodeGob([]byte(kvs))
2013-11-05 15:41:01 +00:00
if err != nil {
return nil, err
2013-11-05 13:59:35 +00:00
}
}
2014-01-21 10:48:16 +00:00
rs := &RedisSessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
2013-09-26 10:07:00 +00:00
return rs, nil
}
// delete redis session by id
func (rp *RedisProvider) SessionDestroy(sid string) error {
2013-10-28 14:19:37 +00:00
c := rp.poollist.Get()
2013-12-14 15:29:17 +00:00
defer c.Close()
2014-01-21 10:48:16 +00:00
c.Do("DEL", sid)
return nil
}
// Impelment method, no used.
func (rp *RedisProvider) SessionGC() {
return
}
// @todo
2013-11-01 16:16:10 +00:00
func (rp *RedisProvider) SessionAll() int {
return 0
}
func init() {
session.Register("redis", redispder)
}