sessions.go (3699B)
1 package sessions 2 3 import ( 4 "log" 5 "net/http" 6 7 "github.com/gin-gonic/gin" 8 "github.com/gorilla/context" 9 "github.com/gorilla/sessions" 10 ) 11 12 const ( 13 DefaultKey = "github.com/gin-contrib/sessions" 14 errorFormat = "[sessions] ERROR! %s\n" 15 ) 16 17 type Store interface { 18 sessions.Store 19 Options(Options) 20 } 21 22 // Wraps thinly gorilla-session methods. 23 // Session stores the values and optional configuration for a session. 24 type Session interface { 25 // ID of the session, generated by stores. It should not be used for user data. 26 ID() string 27 // Get returns the session value associated to the given key. 28 Get(key interface{}) interface{} 29 // Set sets the session value associated to the given key. 30 Set(key interface{}, val interface{}) 31 // Delete removes the session value associated to the given key. 32 Delete(key interface{}) 33 // Clear deletes all values in the session. 34 Clear() 35 // AddFlash adds a flash message to the session. 36 // A single variadic argument is accepted, and it is optional: it defines the flash key. 37 // If not defined "_flash" is used by default. 38 AddFlash(value interface{}, vars ...string) 39 // Flashes returns a slice of flash messages from the session. 40 // A single variadic argument is accepted, and it is optional: it defines the flash key. 41 // If not defined "_flash" is used by default. 42 Flashes(vars ...string) []interface{} 43 // Options sets configuration for a session. 44 Options(Options) 45 // Save saves all sessions used during the current request. 46 Save() error 47 } 48 49 func Sessions(name string, store Store) gin.HandlerFunc { 50 return func(c *gin.Context) { 51 s := &session{name, c.Request, store, nil, false, c.Writer} 52 c.Set(DefaultKey, s) 53 defer context.Clear(c.Request) 54 c.Next() 55 } 56 } 57 58 func SessionsMany(names []string, store Store) gin.HandlerFunc { 59 return func(c *gin.Context) { 60 sessions := make(map[string]Session, len(names)) 61 for _, name := range names { 62 sessions[name] = &session{name, c.Request, store, nil, false, c.Writer} 63 } 64 c.Set(DefaultKey, sessions) 65 defer context.Clear(c.Request) 66 c.Next() 67 } 68 } 69 70 type session struct { 71 name string 72 request *http.Request 73 store Store 74 session *sessions.Session 75 written bool 76 writer http.ResponseWriter 77 } 78 79 func (s *session) ID() string { 80 return s.Session().ID 81 } 82 83 func (s *session) Get(key interface{}) interface{} { 84 return s.Session().Values[key] 85 } 86 87 func (s *session) Set(key interface{}, val interface{}) { 88 s.Session().Values[key] = val 89 s.written = true 90 } 91 92 func (s *session) Delete(key interface{}) { 93 delete(s.Session().Values, key) 94 s.written = true 95 } 96 97 func (s *session) Clear() { 98 for key := range s.Session().Values { 99 s.Delete(key) 100 } 101 } 102 103 func (s *session) AddFlash(value interface{}, vars ...string) { 104 s.Session().AddFlash(value, vars...) 105 s.written = true 106 } 107 108 func (s *session) Flashes(vars ...string) []interface{} { 109 s.written = true 110 return s.Session().Flashes(vars...) 111 } 112 113 func (s *session) Options(options Options) { 114 s.written = true 115 s.Session().Options = options.ToGorillaOptions() 116 } 117 118 func (s *session) Save() error { 119 if s.Written() { 120 e := s.Session().Save(s.request, s.writer) 121 if e == nil { 122 s.written = false 123 } 124 return e 125 } 126 return nil 127 } 128 129 func (s *session) Session() *sessions.Session { 130 if s.session == nil { 131 var err error 132 s.session, err = s.store.Get(s.request, s.name) 133 if err != nil { 134 log.Printf(errorFormat, err) 135 } 136 } 137 return s.session 138 } 139 140 func (s *session) Written() bool { 141 return s.written 142 } 143 144 // shortcut to get session 145 func Default(c *gin.Context) Session { 146 return c.MustGet(DefaultKey).(Session) 147 } 148 149 // shortcut to get session with given name 150 func DefaultMany(c *gin.Context, name string) Session { 151 return c.MustGet(DefaultKey).(map[string]Session)[name] 152 }