diff --git a/_examples/README.md b/_examples/README.md index 0c87b1d9..7fe15ea4 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -139,8 +139,9 @@ * [Basic](cookies/basic/main.go) * [Encode/Decode (with `securecookie`)](cookies/securecookie/main.go) * Sessions - * [Overview](sessions/overview/main.go) - * [Middleware](sessions/middleware/main.go) + * [Overview: Config](sessions/overview/main.go) + * [Overview: Routes](sessions/overview/example/example.go) + * [Basic](sessions/basic/main.go) * [Secure Cookie](sessions/securecookie/main.go) * [Flash Messages](sessions/flash-messages/main.go) * [Databases](sessions/database) diff --git a/_examples/sessions/basic/main.go b/_examples/sessions/basic/main.go new file mode 100644 index 00000000..5827ed88 --- /dev/null +++ b/_examples/sessions/basic/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/kataras/iris/v12/sessions" +) + +const cookieNameForSessionID = "session_id_cookie" + +func secret(ctx iris.Context) { + // Check if user is authenticated + if auth, _ := sessions.Get(ctx).GetBoolean("authenticated"); !auth { + ctx.StatusCode(iris.StatusForbidden) + return + } + + // Print secret message + ctx.WriteString("The cake is a lie!") +} + +func login(ctx iris.Context) { + session := sessions.Get(ctx) + + // Authentication goes here + // ... + + // Set user as authenticated + session.Set("authenticated", true) +} + +func logout(ctx iris.Context) { + session := sessions.Get(ctx) + + // Revoke users authentication + session.Set("authenticated", false) +} + +func main() { + app := iris.New() + sess := sessions.New(sessions.Config{Cookie: cookieNameForSessionID, AllowReclaim: true}) + app.Use(sess.Handler()) + // ^ or comment this line and use sess.Start(ctx) inside your handlers + // instead of sessions.Get(ctx). + + app.Get("/secret", secret) + app.Get("/login", login) + app.Get("/logout", logout) + + app.Listen(":8080") +} diff --git a/_examples/sessions/database/badger/main.go b/_examples/sessions/database/badger/main.go index afdcfcfe..810f55c8 100644 --- a/_examples/sessions/database/badger/main.go +++ b/_examples/sessions/database/badger/main.go @@ -1,13 +1,14 @@ package main import ( - "errors" "time" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/sessions" "github.com/kataras/iris/v12/sessions/sessiondb/badger" + + "github.com/kataras/iris/v12/_examples/sessions/overview/example" ) func main() { @@ -34,75 +35,6 @@ func main() { // sess.UseDatabase(db) - // the rest of the code stays the same. - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) - // set session values - s.Set("name", "iris") - - // test if set here - ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name")) - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - s := sess.Start(ctx) - // set session values - s.Set(key, value) - - // test if set here - ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key)) - }) - - app.Get("/get", func(ctx iris.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("/get/{key}", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString(ctx.Params().Get("key")) - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sess.Start(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - sess.Start(ctx).Clear() - }) - - app.Get("/destroy", func(ctx iris.Context) { - // destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) - - app.Get("/update", func(ctx iris.Context) { - // updates resets the expiration based on the session's `Expires` field. - if err := sess.ShiftExpiration(ctx); err != nil { - if errors.Is(err, sessions.ErrNotFound) { - ctx.StatusCode(iris.StatusNotFound) - } else if errors.Is(err, sessions.ErrNotImplemented) { - ctx.StatusCode(iris.StatusNotImplemented) - } else { - ctx.StatusCode(iris.StatusNotModified) - } - - ctx.Writef("%v", err) - ctx.Application().Logger().Error(err) - } - }) - + app := example.NewApp(sess) app.Listen(":8080") } diff --git a/_examples/sessions/database/boltdb/main.go b/_examples/sessions/database/boltdb/main.go index 23dc727b..11bc9621 100644 --- a/_examples/sessions/database/boltdb/main.go +++ b/_examples/sessions/database/boltdb/main.go @@ -1,7 +1,6 @@ package main import ( - "errors" "os" "time" @@ -9,6 +8,8 @@ import ( "github.com/kataras/iris/v12/sessions" "github.com/kataras/iris/v12/sessions/sessiondb/boltdb" + + "github.com/kataras/iris/v12/_examples/sessions/overview/example" ) func main() { @@ -23,13 +24,17 @@ func main() { }) defer db.Close() // close and unlock the database if application errored. - sess := sessions.New(sessions.Config{ Cookie: "sessionscookieid", Expires: 45 * time.Minute, // <=0 means unlimited life. Defaults to 0. AllowReclaim: true, }) + // + // IMPORTANT: + // + sess.UseDatabase(db) + // The default database's values encoder and decoder // calls the value's `Marshal/Unmarshal` methods (if any) // otherwise JSON is selected, @@ -50,83 +55,9 @@ func main() { // i.e: a transcoder which will allow(on Marshal: return its byte representation and nil error) // or dissalow(on Marshal: return non nil error) certain types. // + // gob.Register(example.BusinessModel{}) // sessions.DefaultTranscoder = sessions.GobTranscoder{} - // - // IMPORTANT: - // - sess.UseDatabase(db) - - // the rest of the code stays the same. - app := iris.New() - app.Logger().SetLevel("debug") - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) - // set session values - s.Set("name", "iris") - - // test if set here - ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name")) - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - s := sess.Start(ctx) - // set session values - s.Set(key, value) - - // test if set here - ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key)) - }) - - app.Get("/get", func(ctx iris.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("/get/{key}", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString(ctx.Params().Get("key")) - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sess.Start(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - sess.Start(ctx).Clear() - }) - - app.Get("/destroy", func(ctx iris.Context) { - // destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) - - app.Get("/update", func(ctx iris.Context) { - // updates resets the expiration based on the session's `Expires` field. - if err := sess.ShiftExpiration(ctx); err != nil { - if errors.Is(err, sessions.ErrNotFound) { - ctx.StatusCode(iris.StatusNotFound) - } else if errors.Is(err, sessions.ErrNotImplemented) { - ctx.StatusCode(iris.StatusNotImplemented) - } else { - ctx.StatusCode(iris.StatusNotModified) - } - - ctx.Writef("%v", err) - ctx.Application().Logger().Error(err) - } - }) - + app := example.NewApp(sess) app.Listen(":8080") } diff --git a/_examples/sessions/database/redis/main.go b/_examples/sessions/database/redis/main.go index 1c5518f5..9891b67a 100644 --- a/_examples/sessions/database/redis/main.go +++ b/_examples/sessions/database/redis/main.go @@ -1,13 +1,14 @@ package main import ( - "errors" "time" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/sessions" "github.com/kataras/iris/v12/sessions/sessiondb/redis" + + "github.com/kataras/iris/v12/_examples/sessions/overview/example" ) // tested with redis version 3.0.503. @@ -42,7 +43,7 @@ func main() { defer db.Close() // close the database connection if application errored. sess := sessions.New(sessions.Config{ - Cookie: "sessionscookieid", + Cookie: "_session_id", Expires: 0, // defaults to 0: unlimited life. Another good value is: 45 * time.Minute, AllowReclaim: true, CookieSecureTLS: true, @@ -53,97 +54,6 @@ func main() { // sess.UseDatabase(db) - // the rest of the code stays the same. - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - - app.Get("/set", func(ctx iris.Context) { - session := sessions.Get(ctx) - // set session values - session.Set("name", "iris") - - // test if set here - ctx.Writef("All ok session value of the 'name' is: %s", session.GetString("name")) - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - session := sessions.Get(ctx) - // set session values - session.Set(key, value) - - // test if set here - ctx.Writef("All ok session value of the '%s' is: %s", key, session.GetString(key)) - }) - - app.Get("/set/int/{key}/{value}", func(ctx iris.Context) { - key := ctx.Params().Get("key") - value, _ := ctx.Params().GetInt("value") - session := sessions.Get(ctx) - // set session values - session.Set(key, value) - valueSet := session.Get(key) - // test if set here - ctx.Writef("All ok session value of the '%s' is: %v", key, valueSet) - }) - - app.Get("/get/{key}", func(ctx iris.Context) { - key := ctx.Params().Get("key") - session := sessions.Get(ctx) - value := session.Get(key) - - ctx.Writef("The '%s' on the /set was: %v", key, value) - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - session := sessions.Get(ctx) - name := session.GetString("name") - - ctx.Writef("The 'name' on the /set was: %s", name) - }) - - app.Get("/get/{key}", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - session := sessions.Get(ctx) - name := session.GetString(ctx.Params().Get("key")) - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sessions.Get(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - sessions.Get(ctx).Clear() - }) - - app.Get("/destroy", func(ctx iris.Context) { - // destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) - - app.Get("/update", func(ctx iris.Context) { - // updates resets the expiration based on the session's `Expires` field. - if err := sess.ShiftExpiration(ctx); err != nil { - if errors.Is(err, sessions.ErrNotFound) { - ctx.StatusCode(iris.StatusNotFound) - } else if errors.Is(err, sessions.ErrNotImplemented) { - ctx.StatusCode(iris.StatusNotImplemented) - } else { - ctx.StatusCode(iris.StatusNotModified) - } - - ctx.Writef("%v", err) - ctx.Application().Logger().Error(err) - } - }) - + app := example.NewApp(sess) app.Listen(":8080") } diff --git a/_examples/sessions/flash-messages/main.go b/_examples/sessions/flash-messages/main.go index dfe6f8f4..acd2a5dd 100644 --- a/_examples/sessions/flash-messages/main.go +++ b/_examples/sessions/flash-messages/main.go @@ -8,16 +8,18 @@ import ( func main() { app := iris.New() - sess := sessions.New(sessions.Config{Cookie: "myappsessionid", AllowReclaim: true}) + + sess := sessions.New(sessions.Config{Cookie: "_session_id", AllowReclaim: true}) + app.Use(sess.Handler()) app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) + s := sessions.Get(ctx) s.SetFlash("name", "iris") ctx.Writef("Message set, is available for the next request") }) app.Get("/get", func(ctx iris.Context) { - s := sess.Start(ctx) + s := sessions.Get(ctx) name := s.GetFlashString("name") if name == "" { ctx.Writef("Empty name!!") @@ -27,7 +29,7 @@ func main() { }) app.Get("/test", func(ctx iris.Context) { - s := sess.Start(ctx) + s := sessions.Get(ctx) name := s.GetFlashString("name") if name == "" { ctx.Writef("Empty name!!") diff --git a/_examples/sessions/middleware/main.go b/_examples/sessions/overview/example/example.go similarity index 55% rename from _examples/sessions/middleware/main.go rename to _examples/sessions/overview/example/example.go index a0c0d734..8f2015d3 100644 --- a/_examples/sessions/middleware/main.go +++ b/_examples/sessions/overview/example/example.go @@ -1,34 +1,21 @@ -package main +package example import ( - "time" + "errors" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/sessions" ) -type businessModel struct { +// BusinessModel is just a Go struct value that we will use in our session example, +// never save sensitive information, like passwords, here. +type BusinessModel struct { Name string } -func main() { +// NewApp returns a new application for showcasing the sessions feature. +func NewApp(sess *sessions.Sessions) *iris.Application { app := iris.New() - sess := sessions.New(sessions.Config{ - // Cookie string, the session's client cookie name, for example: "mysessionid" - // - // Defaults to "irissessionid" - Cookie: "mysessionid", - // it's time.Duration, from the time cookie is created, how long it can be alive? - // 0 means no expire. - // -1 means expire when browser closes - // or set a value, like 2 hours: - Expires: time.Hour * 2, - // if you want to invalid cookies on different subdomains - // of the same host, then enable it. - // Defaults to false. - DisableSubdomainPersistence: false, - }) - app.Use(sess.Handler()) // session is always non-nil inside handlers now. app.Get("/", func(ctx iris.Context) { @@ -51,57 +38,85 @@ func main() { session := sessions.Get(ctx) session.Set("name", "iris") - // test if set here. ctx.Writef("All ok session set to: %s", session.GetString("name")) - - // Set will set the value as-it-is, - // if it's a slice or map - // you will be able to change it on .Get directly! - // Keep note that I don't recommend saving big data neither slices or maps on a session - // but if you really need it then use the `SetImmutable` instead of `Set`. - // Use `SetImmutable` consistently, it's slower. - // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - - session := sessions.Get(ctx) - session.Set(key, value) - - // test if set here - ctx.Writef("All ok session value of the '%s' is: %s", key, session.GetString(key)) }) app.Get("/get", func(ctx iris.Context) { + session := sessions.Get(ctx) + // get a specific value, as string, // if not found then it returns just an empty string. - name := sessions.Get(ctx).GetString("name") + name := session.GetString("name") + + ctx.Writef("The name on the /set was: %s", name) + }) + + app.Get("/set-struct", func(ctx iris.Context) { + session := sessions.Get(ctx) + session.Set("struct", BusinessModel{Name: "John Doe"}) + + ctx.Writef("All ok session value of the 'struct' is: %v", session.Get("struct")) + }) + + app.Get("/get-struct", func(ctx iris.Context) { + session := sessions.Get(ctx) + ctx.Writef("Session value of the 'struct' is: %v", session.Get("struct")) + }) + + app.Get("/set/{key}/{value}", func(ctx iris.Context) { + session := sessions.Get(ctx) + + key := ctx.Params().Get("key") + value := ctx.Params().Get("value") + session.Set(key, value) + + ctx.Writef("All ok session value of the '%s' is: %s", key, session.GetString(key)) + }) + + app.Get("/get/{key}", func(ctx iris.Context) { + session := sessions.Get(ctx) + // get a specific key, as string, if no found returns just an empty string + key := ctx.Params().Get("key") + name := session.GetString(key) ctx.Writef("The name on the /set was: %s", name) }) app.Get("/delete", func(ctx iris.Context) { + session := sessions.Get(ctx) // delete a specific key - sessions.Get(ctx).Delete("name") + session.Delete("name") }) app.Get("/clear", func(ctx iris.Context) { + session := sessions.Get(ctx) // removes all entries. - sessions.Get(ctx).Clear() + session.Clear() }) app.Get("/update", func(ctx iris.Context) { - // updates expire date. - sess.ShiftExpiration(ctx) + session := sessions.Get(ctx) + // shifts the expiration based on the session's `Lifetime`. + if err := session.Man.ShiftExpiration(ctx); err != nil { + if errors.Is(err, sessions.ErrNotFound) { + ctx.StatusCode(iris.StatusNotFound) + } else if errors.Is(err, sessions.ErrNotImplemented) { + ctx.StatusCode(iris.StatusNotImplemented) + } else { + ctx.StatusCode(iris.StatusNotModified) + } + + ctx.Writef("%v", err) + ctx.Application().Logger().Error(err) + } }) app.Get("/destroy", func(ctx iris.Context) { - // destroy, removes the entire session data and cookie - // sess.Destroy(ctx) - // or - sessions.Get(ctx).Destroy() + session := sessions.Get(ctx) + // Man(anager)'s Destroy, removes the entire session data and cookie + session.Man.Destroy(ctx) }) + // Note about Destroy: // // You can destroy a session outside of a handler too, using the: @@ -114,25 +129,26 @@ func main() { // // Use `SetImmutable` consistently, it's slower than `Set`. // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 - app.Get("/set_immutable", func(ctx iris.Context) { - business := []businessModel{{Name: "Edward"}, {Name: "value 2"}} + app.Get("/set-immutable", func(ctx iris.Context) { session := sessions.Get(ctx) + + business := []BusinessModel{{Name: "Edward"}, {Name: "value 2"}} session.SetImmutable("businessEdit", business) - businessGet := session.Get("businessEdit").([]businessModel) + businessGet := session.Get("businessEdit").([]BusinessModel) // try to change it, if we used `Set` instead of `SetImmutable` this // change will affect the underline array of the session's value "businessEdit", but now it will not. businessGet[0].Name = "Gabriel" }) - app.Get("/get_immutable", func(ctx iris.Context) { + app.Get("/get-immutable", func(ctx iris.Context) { valSlice := sessions.Get(ctx).Get("businessEdit") if valSlice == nil { - ctx.HTML("please navigate to the /set_immutable first") + ctx.HTML("please navigate to the /set-immutable first") return } - firstModel := valSlice.([]businessModel)[0] + firstModel := valSlice.([]BusinessModel)[0] // businessGet[0].Name is equal to Edward initially if firstModel.Name != "Edward" { panic("Report this as a bug, immutable data cannot be changed from the caller without re-SetImmutable") @@ -143,5 +159,5 @@ func main() { // the name should remains "Edward" }) - app.Listen(":8080") + return app } diff --git a/_examples/sessions/overview/main.go b/_examples/sessions/overview/main.go index 97b1a379..cf02f589 100644 --- a/_examples/sessions/overview/main.go +++ b/_examples/sessions/overview/main.go @@ -1,50 +1,31 @@ package main import ( - "github.com/kataras/iris/v12" + "time" + "github.com/kataras/iris/v12/_examples/sessions/overview/example" "github.com/kataras/iris/v12/sessions" ) -var ( - cookieNameForSessionID = "mycookiesessionnameid" - sess = sessions.New(sessions.Config{Cookie: cookieNameForSessionID, AllowReclaim: true}) -) - -func secret(ctx iris.Context) { - // Check if user is authenticated - if auth, _ := sess.Start(ctx).GetBoolean("authenticated"); !auth { - ctx.StatusCode(iris.StatusForbidden) - return - } - - // Print secret message - ctx.WriteString("The cake is a lie!") -} - -func login(ctx iris.Context) { - session := sess.Start(ctx) - - // Authentication goes here - // ... - - // Set user as authenticated - session.Set("authenticated", true) -} - -func logout(ctx iris.Context) { - session := sess.Start(ctx) - - // Revoke users authentication - session.Set("authenticated", false) -} - func main() { - app := iris.New() - - app.Get("/secret", secret) - app.Get("/login", login) - app.Get("/logout", logout) + sess := sessions.New(sessions.Config{ + // Cookie string, the session's client cookie name, for example: "_session_id" + // + // Defaults to "irissessionid" + Cookie: "_session_id", + // it's time.Duration, from the time cookie is created, how long it can be alive? + // 0 means no expire, unlimited life. + // -1 means expire when browser closes + // or set a value, like 2 hours: + Expires: time.Hour * 2, + // if you want to invalid cookies on different subdomains + // of the same host, then enable it. + // Defaults to false. + DisableSubdomainPersistence: false, + // Allow getting the session value stored by the request from the same request. + AllowReclaim: true, + }) + app := example.NewApp(sess) app.Listen(":8080") } diff --git a/_examples/sessions/securecookie/main.go b/_examples/sessions/securecookie/main.go index e66effcc..00bfe01a 100644 --- a/_examples/sessions/securecookie/main.go +++ b/_examples/sessions/securecookie/main.go @@ -7,16 +7,17 @@ package main import ( "github.com/kataras/iris/v12" - "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/_examples/sessions/overview/example" + "github.com/gorilla/securecookie" ) func newApp() *iris.Application { app := iris.New() - cookieName := "mycustomsessionid" + cookieName := "_session_id" // AES only supports key sizes of 16, 24 or 32 bytes. // You either need to provide exactly that amount or you derive the key from what you type in. hashKey := []byte("the-big-and-secret-fash-key-here") @@ -30,52 +31,7 @@ func newApp() *iris.Application { AllowReclaim: true, }) - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - // set session values - s := mySessions.Start(ctx) - s.Set("name", "iris") - - // test if set here - ctx.Writef("All ok session set to: %s", s.GetString("name")) - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - s := mySessions.Start(ctx) - name := s.GetString("name") - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - s := mySessions.Start(ctx) - s.Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - mySessions.Start(ctx).Clear() - }) - - app.Get("/update", func(ctx iris.Context) { - // updates expire date with a new date - mySessions.ShiftExpiration(ctx) - }) - - app.Get("/destroy", func(ctx iris.Context) { - // destroy, removes the entire session data and cookie - mySessions.Destroy(ctx) - }) - // Note about destroy: - // - // You can destroy a session outside of a handler too, using the: - // mySessions.DestroyByID - // mySessions.DestroyAll - + app = example.NewApp(mySessions) return app } diff --git a/sessions/provider.go b/sessions/provider.go index effdb230..fa38f2c3 100644 --- a/sessions/provider.go +++ b/sessions/provider.go @@ -30,6 +30,10 @@ func newProvider() *provider { // RegisterDatabase sets a session database. func (p *provider) RegisterDatabase(db Database) { + if db == nil { + return + } + p.mu.Lock() // for any case p.db = db p.mu.Unlock() diff --git a/sessions/transcoding.go b/sessions/transcoding.go index 00d1db2c..41f6a9b3 100644 --- a/sessions/transcoding.go +++ b/sessions/transcoding.go @@ -5,8 +5,13 @@ import ( "encoding/gob" "encoding/json" "reflect" + "time" ) +func init() { + gob.Register(time.Time{}) +} + type ( // Marshaler is the common marshaler interface, used by transcoder. Marshaler interface { @@ -23,6 +28,12 @@ type ( } ) +type ( + defaultTranscoder struct{} + // GobTranscoder can be set to `DefaultTranscoder` to modify the database(s) transcoder. + GobTranscoder struct{} +) + var ( _ Transcoder = (*defaultTranscoder)(nil) _ Transcoder = (*GobTranscoder)(nil) @@ -53,12 +64,6 @@ var ( DefaultTranscoder Transcoder = defaultTranscoder{} ) -type ( - defaultTranscoder struct{} - // GobTranscoder can be set to `DefaultTranscoder` to modify the database(s) transcoder. - GobTranscoder struct{} -) - func (defaultTranscoder) Marshal(value interface{}) ([]byte, error) { if tr, ok := value.(Marshaler); ok { return tr.Marshal(value) @@ -91,17 +96,10 @@ func (GobTranscoder) Marshal(value interface{}) ([]byte, error) { err error ) - switch v := value.(type) { - case reflect.Value: + if v, ok := value.(reflect.Value); ok { err = enc.EncodeValue(v) - case string, - int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, - float32, float64, - complex64, complex128: - err = enc.Encode(&v) - default: - err = enc.Encode(value) + } else { + err = enc.Encode(&value) } if err != nil { @@ -114,10 +112,7 @@ func (GobTranscoder) Marshal(value interface{}) ([]byte, error) { // Unmarshal parses the gob-encoded data "b" and stores the result // in the value pointed to by "outPtr". func (GobTranscoder) Unmarshal(b []byte, outPtr interface{}) error { - var ( - r = bytes.NewBuffer(b) - dec = gob.NewDecoder(r) - ) + dec := gob.NewDecoder(bytes.NewBuffer(b)) if v, ok := outPtr.(reflect.Value); ok { return dec.DecodeValue(v)