Session support for tango
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.

137 lines
2.7 KiB

  1. // Copyright 2015 The Tango Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package session
  5. import (
  6. "net/http"
  7. "time"
  8. "gitea.com/lunny/tango"
  9. )
  10. const (
  11. DefaultMaxAge = 30 * time.Minute
  12. DefaultSessionIdName = "SESSIONID"
  13. DefaultCookiePath = "/"
  14. )
  15. type Sessions struct {
  16. Options
  17. }
  18. type Sessionser interface {
  19. SetSessions(*Sessions)
  20. }
  21. type Options struct {
  22. MaxAge time.Duration
  23. SessionIdName string
  24. Store Store
  25. Generator IdGenerator
  26. Tracker Tracker
  27. OnSessionNew func(*Session)
  28. OnSessionRelease func(*Session)
  29. }
  30. func preOptions(opts []Options) Options {
  31. var opt Options
  32. if len(opts) > 0 {
  33. opt = opts[0]
  34. }
  35. if opt.MaxAge == 0 {
  36. opt.MaxAge = DefaultMaxAge
  37. }
  38. if opt.Store == nil {
  39. opt.Store = NewMemoryStore(opt.MaxAge)
  40. }
  41. if opt.SessionIdName == "" {
  42. opt.SessionIdName = DefaultSessionIdName
  43. }
  44. if opt.Generator == nil {
  45. opt.Generator = NewSha1Generator(string(GenRandKey(16)))
  46. }
  47. if opt.Tracker == nil {
  48. opt.Tracker = NewCookieTracker(opt.SessionIdName, 0, false, DefaultCookiePath)
  49. }
  50. return opt
  51. }
  52. func New(opts ...Options) *Sessions {
  53. opt := preOptions(opts)
  54. sessions := &Sessions{
  55. Options: opt,
  56. }
  57. sessions.Run()
  58. return sessions
  59. }
  60. func Default() *Sessions {
  61. return NewWithTimeout(DefaultMaxAge)
  62. }
  63. func NewWithTimeout(maxAge time.Duration) *Sessions {
  64. return New(Options{MaxAge: maxAge})
  65. }
  66. func (itor *Sessions) Handle(ctx *tango.Context) {
  67. if action := ctx.Action(); action != nil {
  68. if s, ok := action.(Sessionser); ok {
  69. s.SetSessions(itor)
  70. }
  71. if s, ok := action.(Sessioner); ok {
  72. err := s.InitSession(itor, ctx.Req(), ctx.ResponseWriter)
  73. if err != nil {
  74. ctx.Result = err
  75. return
  76. }
  77. }
  78. }
  79. ctx.Next()
  80. }
  81. func (manager *Sessions) SessionFromID(id Id) *Session {
  82. return &Session{
  83. id: id,
  84. maxAge: manager.MaxAge,
  85. manager: manager,
  86. }
  87. }
  88. func (manager *Sessions) SetMaxAge(maxAge time.Duration) {
  89. manager.MaxAge = maxAge
  90. manager.Tracker.SetMaxAge(maxAge)
  91. manager.Store.SetMaxAge(maxAge)
  92. }
  93. func (manager *Sessions) SetIdMaxAge(id Id, maxAge time.Duration) {
  94. manager.Store.SetIdMaxAge(id, maxAge)
  95. }
  96. func (manager *Sessions) Exist(id Id) bool {
  97. return manager.Store.Exist(id)
  98. }
  99. func (manager *Sessions) Session(req *http.Request, rw http.ResponseWriter) *Session {
  100. var sess Session
  101. sess.InitSession(manager, req, rw)
  102. return &sess
  103. }
  104. func (manager *Sessions) Invalidate(rw http.ResponseWriter, session *Session) {
  105. if manager.OnSessionRelease != nil {
  106. manager.OnSessionRelease(session)
  107. }
  108. manager.Store.Clear(session.id)
  109. manager.Tracker.Clear(rw)
  110. }
  111. func (manager *Sessions) Run() error {
  112. return manager.Store.Run()
  113. }