diff --git a/_examples/sessions/database/badger/main.go b/_examples/sessions/database/badger/main.go index 810f55c8..cc245629 100644 --- a/_examples/sessions/database/badger/main.go +++ b/_examples/sessions/database/badger/main.go @@ -26,10 +26,14 @@ func main() { sess := sessions.New(sessions.Config{ Cookie: "sessionscookieid", - Expires: 45 * time.Minute, // <=0 means unlimited life. Defaults to 0. + Expires: 1 * time.Minute, // <=0 means unlimited life. Defaults to 0. AllowReclaim: true, }) + sess.OnDestroy(func(sid string) { + println(sid + " expired and destroyed from memory and its values from database") + }) + // // IMPORTANT: // diff --git a/core/router/api_container.go b/core/router/api_container.go index 9c69ba41..14e2a4ef 100644 --- a/core/router/api_container.go +++ b/core/router/api_container.go @@ -230,6 +230,8 @@ func (api *APIContainer) Any(relativePath string, handlersFn ...interface{}) (ro return } +/* TODO: fix those + // OnErrorCode registers a handlers chain for this `Party` for a specific HTTP status code. // Read more at: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml // Look `OnAnyErrorCode` too. @@ -245,3 +247,4 @@ func (api *APIContainer) OnAnyErrorCode(handlersFn ...interface{}) []*Route { handlers := api.convertHandlerFuncs("/{tail:path}", handlersFn...) return api.Self.OnAnyErrorCode(handlers...) } +*/ diff --git a/go.mod b/go.mod index cf3627ab..c4d7329f 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/dgraph-io/badger/v2 v2.0.3 github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 github.com/fatih/structs v1.1.0 - github.com/golang/protobuf v1.4.1 + github.com/golang/protobuf v1.4.2 github.com/gomodule/redigo v1.8.1 github.com/hashicorp/go-version v1.2.0 github.com/iris-contrib/blackfriday v2.0.0+incompatible @@ -20,7 +20,7 @@ require ( github.com/iris-contrib/pongo2 v0.0.1 github.com/iris-contrib/schema v0.0.1 github.com/json-iterator/go v1.1.9 - github.com/kataras/golog v0.0.13 + github.com/kataras/golog v0.0.15 github.com/kataras/neffos v0.0.15 github.com/kataras/pio v0.0.6 github.com/kataras/sitemap v0.0.5 @@ -31,9 +31,9 @@ require ( github.com/schollz/closestmatch v2.1.0+incompatible github.com/vmihailenco/msgpack/v5 v5.0.0-alpha.2 go.etcd.io/bbolt v1.3.4 - golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 + golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 golang.org/x/text v0.3.2 golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 - gopkg.in/ini.v1 v1.55.0 + gopkg.in/ini.v1 v1.56.0 gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 ) diff --git a/sessions/config.go b/sessions/config.go index 0951959a..b958d494 100644 --- a/sessions/config.go +++ b/sessions/config.go @@ -23,11 +23,6 @@ type ( // CookieSecureTLS set to true if server is running over TLS // and you need the session's cookie "Secure" field to be set true. - // - // Note: The user should fill the Decode configuation field in order for this to work. - // Recommendation: You don't need this to be set to true, just fill the Encode and Decode fields - // with a third-party library like secure cookie, example is provided at the _examples folder. - // // Defaults to false. CookieSecureTLS bool diff --git a/sessions/provider.go b/sessions/provider.go index fa38f2c3..022ddc21 100644 --- a/sessions/provider.go +++ b/sessions/provider.go @@ -10,10 +10,7 @@ type ( // provider contains the sessions and external databases (load and update). // It's the session memory manager provider struct { - // we don't use RWMutex because all actions have read and write at the same action function. - // (or write to a *Session's value which is race if we don't lock) - // narrow locks are fasters but are useless here. - mu sync.Mutex + mu sync.RWMutex sessions map[string]*Session db Database destroyListeners []DestroyListener @@ -22,10 +19,12 @@ type ( // newProvider returns a new sessions provider func newProvider() *provider { - return &provider{ + p := &provider{ sessions: make(map[string]*Session), db: newMemDB(), } + + return p } // RegisterDatabase sets a session database. @@ -41,8 +40,17 @@ func (p *provider) RegisterDatabase(db Database) { // newSession returns a new session from sessionid func (p *provider) newSession(man *Sessions, sid string, expires time.Duration) *Session { + sess := &Session{ + sid: sid, + Man: man, + provider: p, + flashes: make(map[string]*flashMessage), + } + onExpire := func() { - p.Destroy(sid) + p.mu.Lock() + p.deleteSession(sess) + p.mu.Unlock() } lifetime := p.db.Acquire(sid, expires) @@ -62,14 +70,7 @@ func (p *provider) newSession(man *Sessions, sid string, expires time.Duration) lifetime.Begin(expires, onExpire) } - sess := &Session{ - sid: sid, - Man: man, - provider: p, - flashes: make(map[string]*flashMessage), - Lifetime: lifetime, - } - + sess.Lifetime = lifetime return sess } @@ -103,9 +104,9 @@ func (p *provider) UpdateExpiration(sid string, expires time.Duration) error { return nil } - p.mu.Lock() + p.mu.RLock() sess, found := p.sessions[sid] - p.mu.Unlock() + p.mu.RUnlock() if !found { return ErrNotFound } @@ -116,14 +117,14 @@ func (p *provider) UpdateExpiration(sid string, expires time.Duration) error { // Read returns the store which sid parameter belongs func (p *provider) Read(man *Sessions, sid string, expires time.Duration) *Session { - p.mu.Lock() + p.mu.RLock() if sess, found := p.sessions[sid]; found { sess.runFlashGC() // run the flash messages GC, new request here of existing session - p.mu.Unlock() + p.mu.RUnlock() return sess } - p.mu.Unlock() + p.mu.RUnlock() return p.Init(man, sid, expires) // if not found create new } diff --git a/sessions/sessiondb/badger/database.go b/sessions/sessiondb/badger/database.go index d77f76e8..bd14189f 100644 --- a/sessions/sessiondb/badger/database.go +++ b/sessions/sessiondb/badger/database.go @@ -53,6 +53,7 @@ func New(directoryPath string) (*Database, error) { } opts := badger.DefaultOptions(directoryPath) + opts.Logger = golog.Default.Child("[sessionsdb.badger]").DisableNewLine() service, err := badger.Open(opts) if err != nil { diff --git a/sessions/sessions.go b/sessions/sessions.go index 896031fe..41ebe6d9 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -11,13 +11,11 @@ func init() { context.SetHandlerName("iris/sessions.*Handler", "iris.session") } -// A Sessions manager should be responsible to Start a sesion, based -// on a Context, which should return -// a compatible Session interface, type. If the external session manager -// doesn't qualifies, then the user should code the rest of the functions with empty implementation. -// -// Sessions should be responsible to Destroy a session based -// on the Context. +// A Sessions manager should be responsible to Start/Get a sesion, based +// on a Context, which returns a *Session, type. +// It performs automatic memory cleanup on expired sessions. +// It can accept a `Database` for persistence across server restarts. +// A session can set temporarly values (flash messages). type Sessions struct { config Config provider *provider