From 8a7e718bb12e5e848c22dc8dae3ea82d78c0881c Mon Sep 17 00:00:00 2001 From: kataras Date: Wed, 2 Aug 2017 21:52:53 +0300 Subject: [PATCH] Session DB file storage: https://github.com/kataras/iris/issues/702 example added Tested on Windows and worked, waiting for more testers. Former-commit-id: 2b5be0202c1124f424d2276948c3203677f26a56 --- _examples/README.md | 4 +- _examples/sessions/database/file/main.go | 64 +++++++++++++++++++ .../sessions/database/{ => redis}/main.go | 6 +- sessions/sessiondb/file/database.go | 46 +++++++++---- 4 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 _examples/sessions/database/file/main.go rename _examples/sessions/database/{ => redis}/main.go (93%) diff --git a/_examples/README.md b/_examples/README.md index f7e602dc..f6384c97 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -194,7 +194,9 @@ iris session manager lives on its own [package](https://github.com/kataras/iris/ - [Standalone](sessions/standalone/main.go) - [Secure Cookie](sessions/securecookie/main.go) - [Flash Messages](sessions/flash-messages/main.go) -- [Database](sessions/database/main.go) +- [Database](sessions/database) + * [Redis](sessions/database/redis/main.go) + * [File](sessions/database/file/main.go) > You're free to use your own favourite sessions package if you'd like so. diff --git a/_examples/sessions/database/file/main.go b/_examples/sessions/database/file/main.go new file mode 100644 index 00000000..06d28b57 --- /dev/null +++ b/_examples/sessions/database/file/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "github.com/kataras/iris" + "github.com/kataras/iris/context" + + "github.com/kataras/iris/sessions" + "github.com/kataras/iris/sessions/sessiondb/file" +) + +func main() { + db := file.New("./sessions/") + + sess := sessions.New(sessions.Config{Cookie: "sessionscookieid"}) + + // + // IMPORTANT: + // + sess.UseDatabase(db) + + // the rest of the code stays the same. + app := iris.New() + + app.Get("/", func(ctx context.Context) { + ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") + }) + app.Get("/set", func(ctx context.Context) { + s := sess.Start(ctx) + //set session values + s.Set("name", "iris") + + //test if setted here + ctx.Writef("All ok session setted to: %s", s.GetString("name")) + }) + + app.Get("/get", func(ctx context.Context) { + // get a specific key, as string, if no found returns just an empty string + name := sess.Start(ctx).GetString("name") + + ctx.Writef("The name on the /set was: %s", name) + }) + + app.Get("/delete", func(ctx context.Context) { + // delete a specific key + sess.Start(ctx).Delete("name") + }) + + app.Get("/clear", func(ctx context.Context) { + // removes all entries + sess.Start(ctx).Clear() + }) + + app.Get("/destroy", func(ctx context.Context) { + //destroy, removes the entire session data and cookie + sess.Destroy(ctx) + }) + + app.Get("/update", func(ctx context.Context) { + // updates expire date with a new date + sess.ShiftExpiraton(ctx) + }) + + app.Run(iris.Addr(":8080")) +} diff --git a/_examples/sessions/database/main.go b/_examples/sessions/database/redis/main.go similarity index 93% rename from _examples/sessions/database/main.go rename to _examples/sessions/database/redis/main.go index c2a82682..97370072 100644 --- a/_examples/sessions/database/main.go +++ b/_examples/sessions/database/redis/main.go @@ -35,12 +35,12 @@ func main() { ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") }) app.Get("/set", func(ctx context.Context) { - + s := sess.Start(ctx) //set session values - sess.Start(ctx).Set("name", "iris") + s.Set("name", "iris") //test if setted here - ctx.Writef("All ok session setted to: %s", sess.Start(ctx).GetString("name")) + ctx.Writef("All ok session setted to: %s", s.GetString("name")) }) app.Get("/get", func(ctx context.Context) { diff --git a/sessions/sessiondb/file/database.go b/sessions/sessiondb/file/database.go index bce3054b..3f4ea9c9 100644 --- a/sessions/sessiondb/file/database.go +++ b/sessions/sessiondb/file/database.go @@ -11,6 +11,12 @@ import ( "github.com/kataras/golog" ) +var ( + // PathFileMode for creating the sessions directory path, opening and write the session file. + // Defaults to 0666. + PathFileMode uint32 = 0666 +) + // Database is the basic file-storage session database. type Database struct { path string @@ -22,7 +28,8 @@ func New(path string) *Database { if lindex != os.PathSeparator && lindex != '/' { path += string(os.PathSeparator) } - + // create directories if necessary + os.MkdirAll(path, os.FileMode(PathFileMode)) return &Database{path: path} } @@ -32,18 +39,32 @@ func (d *Database) sessPath(sid string) string { // Load loads the values to the underline func (d *Database) Load(sid string) (values map[string]interface{}, expireDate *time.Time) { - val, err := ioutil.ReadFile(d.sessPath(sid)) + sessPath := d.sessPath(sid) + f, err := os.OpenFile(sessPath, os.O_RDONLY, os.FileMode(PathFileMode)) + + if err != nil { + // we don't care if filepath doesn't exists yet, it will be created on Update. + return + } + + defer f.Close() + + val, err := ioutil.ReadAll(f) + + if err != nil { + // we don't care if filepath doesn't exists yet, it will be created on Update. + golog.Errorf("error while reading the session file's data: %v", err) + return + } if err == nil { err = DeserializeBytes(val, &values) + if err != nil { // we care for this error only + golog.Errorf("load error: %v", err) + } } - if err != nil { - golog.Errorf("load error: %v", err) - } - - // no expiration - return + return // no expiration } // serialize the values to be stored as strings inside the session file-storage. @@ -62,8 +83,7 @@ func (d *Database) expireSess(sid string) { // Update updates the session file-storage. func (d *Database) Update(sid string, newValues map[string]interface{}, expireDate *time.Time) { - now := time.Now() - sessPath := d.sessPath(sid) + if len(newValues) == 0 { // means delete by call d.expireSess(sid) return @@ -71,6 +91,8 @@ func (d *Database) Update(sid string, newValues map[string]interface{}, expireDa // delete the file on expiration if expireDate != nil && !expireDate.IsZero() { + now := time.Now() + if expireDate.Before(now) { // already expirated, delete it now and return. d.expireSess(sid) @@ -79,11 +101,11 @@ func (d *Database) Update(sid string, newValues map[string]interface{}, expireDa // otherwise set a timer to delete the file automatically afterDur := expireDate.Sub(now) time.AfterFunc(afterDur, func() { - go os.Remove(sessPath) + d.expireSess(sid) }) } - ioutil.WriteFile(sessPath, serialize(newValues), 0666) + ioutil.WriteFile(d.sessPath(sid), serialize(newValues), os.FileMode(PathFileMode)) } // SerializeBytes serializes the "m" into bytes using gob encoder and and returns the result.