package redis import ( "time" "bytes" "encoding/gob" "github.com/kataras/iris/sessions/sessiondb/redis/service" ) // Database the redis back-end session database for the sessions. type Database struct { redis *service.Service } // New returns a new redis database. func New(cfg ...service.Config) *Database { return &Database{redis: service.New(cfg...)} } // Config returns the configuration for the redis server bridge, you can change them. func (d *Database) Config() *service.Config { return d.redis.Config } // Load loads the values to the underline. func (d *Database) Load(sid string) (datas map[string]interface{}, expireDate *time.Time) { values := make(map[string]interface{}) if !d.redis.Connected { //yes, check every first time's session for valid redis connection d.redis.Connect() _, err := d.redis.PingPong() if err != nil { if err != nil { // don't use to get the logger, just prin these to the console... atm ///TODO: Find a way to use the iris' defined logger via an optional interface to Database. // println("Redis Connection error on Connect: " + err.Error()) // println("But don't panic, auto-switching to memory store right now!") } } } //fetch the values from this session id and copy-> store them val, err := d.redis.GetBytes(sid) if err == nil { // err removed because of previous TODO DeserializeBytes(val, &values) } datas, _ = values["session-data"].(map[string]interface{}) dbExpireDateValue, exists := values["expire-date"] if !exists { return } expireDateValue, ok := dbExpireDateValue.(time.Time) if !ok { return } return datas, &expireDateValue } // serialize the values to be stored as strings inside the Redis, we panic at any serialization error here func serialize(values map[string]interface{}) []byte { val, err := SerializeBytes(values) if err != nil { return nil } return val } // Update updates the real redis store func (d *Database) Update(sid string, newValues map[string]interface{}, expireDate *time.Time) { if len(newValues) == 0 { go d.redis.Delete(sid) } else { datas := map[string]interface{}{"session-data": newValues} if expireDate != nil { datas["expire-date"] = *expireDate } //set/update all the values go d.redis.Set(sid, serialize(datas)) } } // SerializeBytes serializa bytes using gob encoder and returns them func SerializeBytes(m interface{}) ([]byte, error) { buf := new(bytes.Buffer) enc := gob.NewEncoder(buf) err := enc.Encode(m) if err == nil { return buf.Bytes(), nil } return nil, err } // DeserializeBytes converts the bytes to an object using gob decoder func DeserializeBytes(b []byte, m interface{}) error { dec := gob.NewDecoder(bytes.NewBuffer(b)) return dec.Decode(m) //no reference here otherwise doesn't work because of go remote object }