mirror of
https://github.com/schollz/cowyo.git
synced 2023-08-10 21:13:00 +03:00
140 lines
3.9 KiB
Go
140 lines
3.9 KiB
Go
package gsm
|
|
|
|
import (
|
|
"encoding/base32"
|
|
"github.com/gorilla/securecookie"
|
|
"github.com/gorilla/sessions"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// NewDumbMemorySessionStoreWithValueStorer return a new dumb in-memory
|
|
// map and no expiration backed by a ValueStorer. Good for local
|
|
// development so you don't have to run
|
|
// memcached on your laptop just to fire up
|
|
// your app and hack away.
|
|
// A ValueStorer is used to store an encrypted sessionID. The encrypted sessionID is used to access
|
|
// the dumb in-memory map and get the session values.
|
|
func NewDumbMemorySessionStoreWithValueStorer(valueStorer ValueStorer) *DumbMemoryStore {
|
|
|
|
if valueStorer == nil {
|
|
panic("Cannot have nil ValueStorer")
|
|
}
|
|
|
|
keyPair := []byte("stub")
|
|
|
|
return &DumbMemoryStore{
|
|
Codecs: securecookie.CodecsFromPairs(keyPair),
|
|
Options: &sessions.Options{
|
|
Path: "/",
|
|
MaxAge: 86400 * 30,
|
|
},
|
|
Data: make(map[string]string),
|
|
ValueStorer: valueStorer,
|
|
}
|
|
}
|
|
|
|
// Sessions implemented with a dumb in-memory
|
|
// map and no expiration. Good for local
|
|
// development so you don't have to run
|
|
// memcached on your laptop just to fire up
|
|
// your app and hack away.
|
|
func NewDumbMemorySessionStore() *DumbMemoryStore {
|
|
return NewDumbMemorySessionStoreWithValueStorer(&CookieStorer{})
|
|
}
|
|
|
|
// DumbMemoryStore stores sessions in memcache
|
|
//
|
|
type DumbMemoryStore struct {
|
|
Codecs []securecookie.Codec
|
|
Options *sessions.Options // default configuration
|
|
Data map[string]string // session data goes here
|
|
ValueStorer ValueStorer
|
|
}
|
|
|
|
// MaxLength restricts the maximum length of new sessions to l.
|
|
// If l is 0 there is no limit to the size of a session, use with caution.
|
|
// The default for a new DumbMemoryStore is 4096.
|
|
func (s *DumbMemoryStore) MaxLength(l int) {
|
|
for _, c := range s.Codecs {
|
|
if codec, ok := c.(*securecookie.SecureCookie); ok {
|
|
codec.MaxLength(l)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get returns a session for the given name after adding it to the registry.
|
|
//
|
|
// See CookieStore.Get().
|
|
func (s *DumbMemoryStore) Get(r *http.Request, name string) (*sessions.Session, error) {
|
|
return sessions.GetRegistry(r).Get(s, name)
|
|
}
|
|
|
|
// New returns a session for the given name without adding it to the registry.
|
|
//
|
|
// See CookieStore.New().
|
|
func (s *DumbMemoryStore) New(r *http.Request, name string) (*sessions.Session, error) {
|
|
session := sessions.NewSession(s, name)
|
|
opts := *s.Options
|
|
session.Options = &opts
|
|
session.IsNew = true
|
|
var err error
|
|
if value, errCookie := s.ValueStorer.GetValueForSessionName(r, name); errCookie == nil {
|
|
err = securecookie.DecodeMulti(name, value, &session.ID, s.Codecs...)
|
|
if err == nil {
|
|
err = s.load(session)
|
|
if err == nil {
|
|
session.IsNew = false
|
|
}
|
|
}
|
|
}
|
|
return session, err
|
|
}
|
|
|
|
// Save adds a single session to the response.
|
|
func (s *DumbMemoryStore) Save(r *http.Request, w http.ResponseWriter,
|
|
session *sessions.Session) error {
|
|
if session.ID == "" {
|
|
// Because the ID is used in the filename, encode it to
|
|
// use alphanumeric characters only.
|
|
session.ID = strings.TrimRight(
|
|
base32.StdEncoding.EncodeToString(
|
|
securecookie.GenerateRandomKey(32)), "=")
|
|
}
|
|
if err := s.save(session); err != nil {
|
|
return err
|
|
}
|
|
encoded, err := securecookie.EncodeMulti(session.Name(), session.ID,
|
|
s.Codecs...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := s.ValueStorer.SetValueForSessionName(w, session.Name(), encoded, session.Options); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// save writes encoded session.Values using the memcache client
|
|
func (s *DumbMemoryStore) save(session *sessions.Session) error {
|
|
encoded, err := securecookie.EncodeMulti(session.Name(), session.Values,
|
|
s.Codecs...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
s.Data[session.ID] = encoded
|
|
|
|
return nil
|
|
}
|
|
|
|
// load reads a file and decodes its content into session.Values.
|
|
func (s *DumbMemoryStore) load(session *sessions.Session) error {
|
|
|
|
if err := securecookie.DecodeMulti(session.Name(), string(s.Data[session.ID]),
|
|
&session.Values, s.Codecs...); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|