You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

91 lines
2.3 KiB

  1. package handlers
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. // SessionStore interface, must be implemented by any store to be used
  7. // for session storage.
  8. type SessionStore interface {
  9. Get(id string) (*Session, error) // Get the session from the store
  10. Set(sess *Session) error // Save the session in the store
  11. Delete(id string) error // Delete the session from the store
  12. Clear() error // Delete all sessions from the store
  13. Len() int // Get the number of sessions in the store
  14. }
  15. // In-memory implementation of a session store. Not recommended for production
  16. // use.
  17. type MemoryStore struct {
  18. l sync.RWMutex
  19. m map[string]*Session
  20. capc int
  21. }
  22. // Create a new memory store.
  23. func NewMemoryStore(capc int) *MemoryStore {
  24. m := &MemoryStore{}
  25. m.capc = capc
  26. m.newMap()
  27. return m
  28. }
  29. // Get the number of sessions saved in the store.
  30. func (this *MemoryStore) Len() int {
  31. return len(this.m)
  32. }
  33. // Get the requested session from the store.
  34. func (this *MemoryStore) Get(id string) (*Session, error) {
  35. this.l.RLock()
  36. defer this.l.RUnlock()
  37. return this.m[id], nil
  38. }
  39. // Save the session to the store.
  40. func (this *MemoryStore) Set(sess *Session) error {
  41. this.l.Lock()
  42. defer this.l.Unlock()
  43. this.m[sess.ID()] = sess
  44. if sess.IsNew() {
  45. // Since the memory store doesn't marshal to a string without the isNew, if it is left
  46. // to true, it will stay true forever.
  47. sess.isNew = false
  48. // Expire in the given time. If the maxAge is 0 (which means browser-session lifetime),
  49. // expire in a reasonable delay, 2 days. The weird case of a negative maxAge will
  50. // cause the immediate Delete call.
  51. wait := sess.MaxAge()
  52. if wait == 0 {
  53. wait = 2 * 24 * time.Hour
  54. }
  55. go func() {
  56. // Clear the session after the specified delay
  57. <-time.After(wait)
  58. this.Delete(sess.ID())
  59. }()
  60. }
  61. return nil
  62. }
  63. // Delete the specified session ID from the store.
  64. func (this *MemoryStore) Delete(id string) error {
  65. this.l.Lock()
  66. defer this.l.Unlock()
  67. delete(this.m, id)
  68. return nil
  69. }
  70. // Clear all sessions from the store.
  71. func (this *MemoryStore) Clear() error {
  72. this.l.Lock()
  73. defer this.l.Unlock()
  74. this.newMap()
  75. return nil
  76. }
  77. // Re-create the internal map, dropping all existing sessions.
  78. func (this *MemoryStore) newMap() {
  79. this.m = make(map[string]*Session, this.capc)
  80. }