• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stackus / sessions / 14847484626

05 May 2025 10:24PM UTC coverage: 78.595% (-0.04%) from 78.634%
14847484626

push

github

stackus
skip saving unchanged sessions

- Use a simple hash of the session data and cookie options to determine if the session data has changed.

33 of 42 new or added lines in 2 files covered. (78.57%)

481 of 612 relevant lines covered (78.59%)

22.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.67
/manager.go
1
package sessions
2

3
import (
4
        "net/http"
5
)
6

7
type SessionManager[T any] interface {
8
        Get(r *http.Request) (*Session[T], error)
9
        Save(w http.ResponseWriter, r *http.Request, session *Session[T]) error
10
}
11

12
type sessionManager[T any] struct {
13
        options CookieOptions
14
        store   Store
15
        codecs  []Codec
16
}
17

18
func NewSessionManager[T any](options CookieOptions, store Store, codecs ...Codec) SessionManager[T] {
51✔
19
        return &sessionManager[T]{
51✔
20
                options: options,
51✔
21
                store:   store,
51✔
22
                codecs:  codecs,
51✔
23
        }
51✔
24
}
51✔
25

26
// Get returns a session for the given request and cookie name.
27
//
28
// The returned session will inherit the options set in the manager.
29
func (sm *sessionManager[T]) Get(r *http.Request) (*Session[T], error) {
51✔
30
        reg := getRegistry(r)
51✔
31
        if session := reg.get(sm.options.Name); session != nil {
51✔
32
                if s, ok := session.(*Session[T]); ok {
×
33
                        return s, nil
×
34
                }
×
35
                return nil, ErrInvalidSessionType
×
36
        }
37

38
        proxy := &SessionProxy{
51✔
39
                Values:  new(T),
51✔
40
                req:     r,
51✔
41
                options: &sm.options,
51✔
42
                codecs:  sm.codecs,
51✔
43
        }
51✔
44

51✔
45
        if initable, ok := proxy.Values.(interface{ Init() }); ok {
57✔
46
                initable.Init()
6✔
47
        }
6✔
48

49
        var err error
51✔
50
        if c, cErr := r.Cookie(sm.options.Name); cErr == nil {
81✔
51
                err = sm.store.Get(r.Context(), proxy, c.Value)
30✔
52
        } else {
51✔
53
                // start with IsNew = true; if the store needs or wants to set it to false, it may
21✔
54
                proxy.IsNew = true
21✔
55
                err = sm.store.New(r.Context(), proxy)
21✔
56
        }
21✔
57

58
        if err != nil {
54✔
59
                return nil, err
3✔
60
        }
3✔
61

62
        values, ok := proxy.Values.(*T)
48✔
63
        if !ok {
51✔
64
                return nil, ErrInvalidSessionType
3✔
65
        }
3✔
66

67
        sHash := &sessionHash[T]{
45✔
68
                Data:    *values,
45✔
69
                Options: *proxy.options,
45✔
70
        }
45✔
71

45✔
72
        hash, err := sHash.Hash()
45✔
73
        if err != nil {
45✔
NEW
74
                return nil, err
×
NEW
75
        }
×
76

77
        session := &Session[T]{
45✔
78
                Values:   *values,
45✔
79
                IsNew:    proxy.IsNew,
45✔
80
                storeKey: proxy.ID,
45✔
81
                manager:  sm,
45✔
82
                hash:     hash,
45✔
83
                options:  *proxy.options,
45✔
84
        }
45✔
85

45✔
86
        reg.set(sm.options.Name, session)
45✔
87

45✔
88
        return session, nil
45✔
89
}
90

91
func (sm *sessionManager[T]) Save(w http.ResponseWriter, r *http.Request, session *Session[T]) error {
39✔
92
        if !session.IsNew {
63✔
93
                // create and compare the hash
24✔
94
                sHash := &sessionHash[T]{
24✔
95
                        Data:    session.Values,
24✔
96
                        Options: session.options,
24✔
97
                }
24✔
98

24✔
99
                if equal, err := sHash.Compare(session.hash); err != nil {
24✔
NEW
100
                        return err
×
101
                } else if equal {
27✔
102
                        return nil
3✔
103
                }
3✔
104
        }
105

106
        proxy := &SessionProxy{
36✔
107
                req:     r,
36✔
108
                resp:    w,
36✔
109
                options: &session.options,
36✔
110
                codecs:  sm.codecs,
36✔
111
                Values:  session.Values,
36✔
112
                ID:      session.storeKey,
36✔
113
                IsNew:   session.IsNew,
36✔
114
        }
36✔
115

36✔
116
        return sm.store.Save(r.Context(), proxy)
36✔
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc