@@ -3,8 +3,11 @@ package fasthttpsession
33import (
44 "errors"
55 "fmt"
6- "github.com/valyala/fasthttp "
6+ "reflect "
77 "time"
8+
9+ cmap "github.com/orcaman/concurrent-map"
10+ "github.com/valyala/fasthttp"
811)
912
1013var version = "v0.0.1"
@@ -14,6 +17,7 @@ type Session struct {
1417 provider Provider
1518 config * Config
1619 cookie * Cookie
20+ ccmap cmap.ConcurrentMap
1721}
1822
1923var providers = make (map [string ]Provider )
@@ -54,6 +58,18 @@ func NewSession(cfg *Config) *Session {
5458 return session
5559}
5660
61+ // ChangeCookieName => Update cookie name
62+ func (s * Session ) ChangeCookieName (cookieName string ) {
63+ if cookieName != "" {
64+ s .config .CookieName = cookieName
65+ }
66+ }
67+
68+ // ChangeNeedStoreInMap => Change store ccmap between : SessionStore <=> ctx
69+ func (s * Session ) ChangeNeedStoreInMap (controlFlg bool ) {
70+ s .config .NeedStoreInMap = controlFlg
71+ }
72+
5773// set session provider and provider config
5874func (s * Session ) SetProvider (providerName string , providerConfig ProviderConfig ) error {
5975 provider , ok := providers [providerName ]
@@ -91,12 +107,45 @@ func (s *Session) gc() {
91107 }
92108}
93109
110+ func getCtxPointer (ctx * fasthttp.RequestCtx ) string {
111+ var ctxPtr uintptr = reflect .ValueOf (ctx ).Pointer ()
112+ return fmt .Sprintf ("0x%x" , ctxPtr )
113+ }
114+
115+ func (s * Session ) GetSessionStoreWithCtx (ctx * fasthttp.RequestCtx ) (sessionStore SessionStore , err error ) {
116+ if s .config .NeedStoreInMap == false {
117+ return sessionStore , errors .New (fmt .Sprintf ("Not support this method in constructor" ))
118+ }
119+
120+ if tmp , ok := s .ccmap .Get (getCtxPointer (ctx )); ok {
121+ return tmp .(fasthttpsession.SessionStore ), nil
122+ }
123+ return sessionStore , errors .New (fmt .Sprintf ("Session store is empty" ))
124+ }
125+
126+ func (s * Session ) SetSessionStoreWithCtx (ctx * fasthttp.RequestCtx , sessionStore SessionStore ) {
127+ s .ccmap .Set (getCtxPointer (ctx ), sessionStore )
128+ }
129+
130+ func (s * Session ) RemoveSessionStoreWithCtx (ctx * fasthttp.RequestCtx ) bool {
131+ if s .config .NeedStoreInMap == false {
132+ return true
133+ }
134+
135+ var ctxStr = getCtxPointer (ctx )
136+ ok := s .ccmap .Has (ctxStr )
137+ if ok {
138+ s .ccmap .Remove (ctxStr )
139+ return true
140+ }
141+ return false
142+ }
143+
94144// session start
95145// 1. get sessionId from fasthttp ctx
96146// 2. if sessionId is empty, generator sessionId and set response Set-Cookie
97147// 3. return session provider store
98148func (s * Session ) Start (ctx * fasthttp.RequestCtx ) (sessionStore SessionStore , err error ) {
99-
100149 if s .provider == nil {
101150 return sessionStore , errors .New ("session start error, not set provider" )
102151 }
@@ -109,10 +158,11 @@ func (s *Session) Start(ctx *fasthttp.RequestCtx) (sessionStore SessionStore, er
109158 return sessionStore , errors .New ("session generator sessionId is empty" )
110159 }
111160 }
161+
112162 // read provider session store
113163 sessionStore , err = s .provider .ReadStore (sessionId )
114164 if err != nil {
115- return
165+ return sessionStore , errors . New ( fmt . Sprintf ( "Error when read session data : %s" , err . Error ()))
116166 }
117167
118168 // encode cookie value
@@ -131,15 +181,18 @@ func (s *Session) Start(ctx *fasthttp.RequestCtx) (sessionStore SessionStore, er
131181 ctx .Response .Header .Set (s .config .SessionNameInHttpHeader , sessionId )
132182 }
133183
134- return
184+ if s .config .NeedStoreInMap {
185+ s .SetSessionStoreWithCtx (ctx , sessionStore )
186+ }
187+
188+ return sessionStore , nil
135189}
136190
137191// get session id
138192// 1. get session id by reading from cookie
139193// 2. get session id from query
140194// 3. get session id from http headers
141195func (s * Session ) GetSessionId (ctx * fasthttp.RequestCtx ) string {
142-
143196 cookieByte := ctx .Request .Header .Cookie (s .config .CookieName )
144197 if len (cookieByte ) > 0 {
145198 return s .config .Decode (string (cookieByte ))
@@ -177,15 +230,16 @@ func (s *Session) Regenerate(ctx *fasthttp.RequestCtx) (sessionStore SessionStor
177230 // encode cookie value
178231 encodeCookieValue := s .config .Encode (sessionId )
179232
180- oldSessionId := s .GetSessionId (ctx )
181233 // regenerate provider session store
234+ oldSessionId := s .GetSessionId (ctx )
182235 if oldSessionId != "" {
183236 sessionStore , err = s .provider .Regenerate (oldSessionId , sessionId )
184237 } else {
185238 sessionStore , err = s .provider .ReadStore (sessionId )
186239 }
240+
187241 if err != nil {
188- return
242+ return sessionStore , errors . New ( fmt . Sprintf ( "Error when read session data : %s" , err . Error ()))
189243 }
190244
191245 // reset response cookie
@@ -202,11 +256,18 @@ func (s *Session) Regenerate(ctx *fasthttp.RequestCtx) (sessionStore SessionStor
202256 ctx .Response .Header .Set (s .config .SessionNameInHttpHeader , sessionId )
203257 }
204258
205- return
259+ if s .config .NeedStoreInMap {
260+ s .SetSessionStoreWithCtx (ctx , sessionStore )
261+ }
262+
263+ return sessionStore , nil
206264}
207265
208266// destroy session in fasthttp ctx
209267func (s * Session ) Destroy (ctx * fasthttp.RequestCtx ) {
268+ if s .config .NeedStoreInMap {
269+ defer s .RemoveSessionStoreWithCtx (ctx )
270+ }
210271
211272 // delete header if sessionId in http Header
212273 if s .config .SessionIdInHttpHeader {
0 commit comments