...
1 package memory
2
3 import (
4 "bytes"
5 "encoding/base32"
6 "encoding/gob"
7 "fmt"
8 "net/http"
9 "strings"
10
11 "github.com/gorilla/securecookie"
12 "github.com/gorilla/sessions"
13 )
14
15
16
17
18
19 type MemStore struct {
20 Codecs []securecookie.Codec
21 Options *sessions.Options
22 cache *cache
23 }
24
25 type valueType map[interface{}]interface{}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 func NewMemStore(keyPairs ...[]byte) *MemStore {
43 store := MemStore{
44 Codecs: securecookie.CodecsFromPairs(keyPairs...),
45 Options: &sessions.Options{
46 Path: "/",
47 MaxAge: 86400 * 30,
48 },
49 cache: newCache(),
50 }
51 store.MaxAge(store.Options.MaxAge)
52 return &store
53 }
54
55
56
57
58
59
60
61
62 func (m *MemStore) Get(r *http.Request, name string) (*sessions.Session, error) {
63 return sessions.GetRegistry(r).Get(m, name)
64 }
65
66
67
68
69
70
71 func (m *MemStore) New(r *http.Request, name string) (*sessions.Session, error) {
72 session := sessions.NewSession(m, name)
73 options := *m.Options
74 session.Options = &options
75 session.IsNew = true
76
77 c, err := r.Cookie(name)
78 if err != nil {
79
80 return session, nil
81 }
82
83 err = securecookie.DecodeMulti(name, c.Value, &session.ID, m.Codecs...)
84 if err != nil {
85
86 return session, err
87 }
88
89 v, ok := m.cache.value(session.ID)
90 if !ok {
91
92
93 return session, nil
94 }
95
96
97 session.Values = m.copy(v)
98 session.IsNew = false
99 return session, nil
100 }
101
102
103
104 func (m *MemStore) Save(_ *http.Request, w http.ResponseWriter, s *sessions.Session) error {
105 var cookieValue string
106 if s.Options.MaxAge < 0 {
107 cookieValue = ""
108 m.cache.delete(s.ID)
109 for k := range s.Values {
110 delete(s.Values, k)
111 }
112 } else {
113 if s.ID == "" {
114 s.ID = strings.TrimRight(base32.StdEncoding.EncodeToString(securecookie.GenerateRandomKey(32)), "=")
115 }
116 encrypted, err := securecookie.EncodeMulti(s.Name(), s.ID, m.Codecs...)
117 if err != nil {
118 return err
119 }
120 cookieValue = encrypted
121 m.cache.setValue(s.ID, m.copy(s.Values))
122 }
123 http.SetCookie(w, sessions.NewCookie(s.Name(), cookieValue, s.Options))
124 return nil
125 }
126
127
128
129
130 func (m *MemStore) MaxAge(age int) {
131 m.Options.MaxAge = age
132
133
134 for _, codec := range m.Codecs {
135 if sc, ok := codec.(*securecookie.SecureCookie); ok {
136 sc.MaxAge(age)
137 }
138 }
139 }
140
141 func (m *MemStore) copy(v valueType) valueType {
142 var buf bytes.Buffer
143 enc := gob.NewEncoder(&buf)
144 dec := gob.NewDecoder(&buf)
145 err := enc.Encode(v)
146 if err != nil {
147 panic(fmt.Errorf("could not copy memstore value. Encoding to gob failed: %v", err))
148 }
149 var value valueType
150 err = dec.Decode(&value)
151 if err != nil {
152 panic(fmt.Errorf("could not copy memstore value. Decoding from gob failed: %v", err))
153 }
154 return value
155 }
156
View as plain text