Skip to content

Commit a3b0aa7

Browse files
vividvillaknadh
andauthored
Refactor the lib and break to v3 (#35)
* Refactor the session `AutoCreate` behaviour. This is a breaking change. * feat: refactor tests * fix: update code comments * refactor: remove Commit() pattern and introduce setMulti to store interface - remove Commit() pattern, Set and SetMulti should immediately set the values to backend. - rename LoadValues() to CacheAll() and update cache on Set, SetMulti, Delete and Clear calls. * fix: update goredis package to implement latest store interface * feat: v3 refactor - Update store interface to take session ID instead of returning on Create() - Introduce hooks to generate and validate session ID in manager. By default use alpha-numeric 32 length ID. - Rename get and set cookie register method to `SetCookieHooks`. - Ditch ErrFieldNotFound error and get/set supposed to return Nil instead. * refactor: conv package to v3 spec * feat: migrate memory store to v3 spec * refactor: redis package to v3 spec * refactor: securecookie package to v3 spec * refactor: postgres package to v3 spec * fix: Clear() should only clear the values and not session * feat: add Destroy() which deletes the dession from backend * chore: update README and lib comments * fix: incorrect store Delete() method implementation * fix: update store version to v3 * fix: update examples to v3 * fix: refactor examples module structure --------- Co-authored-by: Kailash Nadh <[email protected]>
1 parent 205c1e0 commit a3b0aa7

File tree

41 files changed

+2808
-3963
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2808
-3963
lines changed

README.md

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,41 @@ Most session libraries are highly opinionated and hard-wired to work with `net/h
99
## Features
1010
1. Framework/network library agnostic.
1111
2. Simple API and with support for primitive data types. Complex types can be stored using own encoding/decoding.
12-
3. Pre-built redis/postgres/in-memory stores that can be separately installed.
12+
3. Pre-built redis/postgres/in-memory/securecookie stores that can be separately installed.
1313
4. Multiple session instances with custom handlers and different backend stores.
1414

1515
## Installation
1616
Install `simplesessions` and all [available stores](/stores).
1717

1818
```shell
19-
go get -u github.com/vividvilla/simplesessions
19+
go get -u github.com/vividvilla/simplesessions/v3
2020

21-
# Install the requrired store: memory|goredis|redis|postgres
22-
go get -u github.com/vividvilla/simplesessions/stores/goredis
21+
# Install the requrired store: memory|redis|postgres|securecookie
22+
go get -u github.com/vividvilla/simplesessions/v3/stores/redis
23+
go get -u github.com/vividvilla/simplesessions/v3/stores/postgres
2324
```
2425

2526
# Stores
2627
Sessions can be stored to any backend by implementing the [store](/store.go) interface. The following stores are bundled.
2728

28-
* [in-memory](/stores/memory)
2929
* [redis](/stores/redis)
30+
* [postgres](/stores/postgres)
31+
* [in-memory](/stores/memory)
3032
* [secure cookie](/stores/securecookie)
3133

3234
# Usage
3335
Check the [examples](/examples) directory for complete examples.
3436

3537
## Connecting a store
36-
Stores can be registered to a session instance by using `Use` method.
38+
Stores can be registered to a session instance by using `Use` method. Check individual [Stores](#stores) docs for more details.
3739

3840
```go
3941
sess := simplesessions.New(simplesessions.Options{})
40-
sess.UseStore(memory.New())
42+
sess.UseStore(store.New())
4143
```
4244

4345
## Connecting an HTTP handler
44-
Any HTTP library can be connected to simplesessions by registering the `RegisterGetCookie()` and `RegisterSetCookie()` callbacks. The below example shows a simple `net/http` usecase. Another example showing `fasthttp` can be found [here](/examples).
46+
Any HTTP library can be connected to simplesessions by registering the get and set cookie hooks using `SetCookieHooks()`. The below example shows a simple `net/http` usecase. Another example showing `fasthttp` can be found [here](/examples).
4547

4648
```go
4749
var sessMan *simplesessions.Manager
@@ -81,61 +83,104 @@ func setCookie(cookie *http.Cookie, w interface{}) error {
8183
func handler(w http.ResponseWriter, r *http.Request) {
8284
// Use method `Acquire` to acquire a session before you access the session.
8385
// Acquire takes read, write interface and context respectively.
84-
// Read interface sent to callback registered with `RegisterGetCookie`
85-
// and write interface is sent to callback registered with `RegisterWriteCookie`
86+
// Read interface sent to callback registered with get cookie hook
87+
// and write interface is sent to callback registered with write cookie hook
88+
// set using `SetCookieHooks()` method.
89+
//
8690
// Optionally `context` can be sent which is usually request context where acquire
8791
// session will get previously loaded session. This is useful if you have multiple
8892
// middlewares accessing sessions. New sessions will be created in first middleware which
8993
// does `Acquire` and will be reused in other places.
90-
sess, err := sessMan.Acquire(r, w, nil)
91-
92-
// Use 'Set` and `Commit` to set a field for session.
93-
// 'Set` ideally doesn't persist the value to store unless method `Commit` is called.
94-
// But note that its up to the store you are using to decide to
95-
// persist data only on `commit` or persist on `Set` itself.
96-
// Stores like redis, db etc should persist on `Commit` while in-memory does on `Set`.
97-
// No matter what store you use its better to explicitly
98-
// call `Commit` method when you set all the values.
94+
//
95+
// If `Options.EnableAutoCreate` is set to True then if session doesn't exist it will
96+
// be immediately created and returned. Bydefault its set to False so if session doesn't
97+
// exist then `ErrInvalidSession` error is returned.
98+
sess, err := sessMan.Acquire(nil, r, w)
99+
100+
// If session doesn't exist then create new session.
101+
// In a traditional login flow you can create a new session once user completes the login flow.
102+
if err == simplesessions.ErrInvalidSession {
103+
sess, err = sessMan.NewSession(r, w)
104+
}
105+
106+
// Use 'Set` or `SetMulti` to set a field for session.
99107
err = sess.Set("somekey", "somevalue")
100-
err = sess.Set("someotherkey", 10)
101-
err = sess.Commit()
108+
err = sess.SetMulti(map[string]interface{}{
109+
"k1": "v1",
110+
"k2": "v2",
111+
})
102112

103113
// Use `Get` method to get a field from current session. The result will be an interface
104114
// so you can use helper methods like
105115
// `String', `Int`, `Int64`, `UInt64`, `Float64`, `Bytes`, `Bool`.
106116
val, err := sess.String(sess.Get("somekey"))
117+
fmt.Println("val=", val)
107118

108119
// Use `GetAll` to get map of all fields from session.
109120
// The result is map of string and interface you can use helper methods to type cast it.
110-
val, err := sess.GetAll()
121+
all, err := sess.GetAll()
122+
fmt.Println("all=", all)
111123

112124
// Use `GetMulti` to get values for given fields from session.
113125
// The result is map of string and interface you can use helper methods to type cast it.
114126
// If key is not there then store should ideally send `nil` value for given key.
115-
val, err := sess.GetMulti("somekey", "someotherkey")
127+
vals, err := sess.GetMulti("somekey", "someotherkey")
128+
fmt.Println("vals=", vals)
116129

117130
// Use `Delete` to delete a field from session.
118-
err := sess.Delete("somekey")
131+
err = sess.Delete("somekey")
132+
133+
// Use `Clear` to empty the session but to keep the session alive.
134+
err = sess.Clear()
119135

120-
// Use `Clear` to clear session from store.
121-
err := sess.Clear()
136+
// Use `Destroy` to clear session from store and cookie.
137+
err = sess.Destroy()
122138

123139
fmt.Fprintf(w, "success")
124140
}
125141

126142
func main() {
127143
// Create a session manager with custom options like cookie name,
128144
// cookie domain, is secure cookie etc. Check `Options` struct for more options.
129-
sessMan := simplesessions.New(simplesessions.Options{})
145+
sessMan := simplesessions.New(simplesessions.Options{
146+
// If set to true then `Acquire()` method will create new session instead of throwing
147+
// `ErrInvalidSession` when the session doesn't exist. By default its set to false.
148+
EnableAutoCreate: false,
149+
Cookie: simplesessions.CookieOptions{
150+
// Name sets http cookie name. This is also sent as cookie name in `GetCookie` callback.
151+
Name: "session",
152+
// Domain sets hostname for the cookie. Domain specifies allowed hosts to receive the cookie.
153+
Domain: "example.com",
154+
// Path sets path for the cookie. Path indicates a URL path that must exist in the requested URL in order to send the cookie header.
155+
Path: "/",
156+
// IsSecure marks the cookie as secure cookie (only sent in HTTPS).
157+
IsSecure: true,
158+
// IsHTTPOnly marks the cookie as http only cookie. JS won't be able to access the cookie so prevents XSS attacks.
159+
IsHTTPOnly: true,
160+
// SameSite sets allows you to declare if your cookie should be restricted to a first-party or same-site context.
161+
SameSite: http.SameSiteDefaultMode,
162+
// Expires sets absolute expiration date and time for the cookie.
163+
// If both Expires and MaxAge are sent then MaxAge takes precedence over Expires.
164+
// Cookies without a Max-age or Expires attribute – are deleted when the current session ends
165+
// and some browsers use session restoring when restarting. This can cause session cookies to last indefinitely.
166+
Expires: time.Now().Add(time.Hour * 24),
167+
// Sets the cookie's expiration in seconds from the current time, internally its rounder off to nearest seconds.
168+
// If both Expires and MaxAge are sent then MaxAge takes precedence over Expires.
169+
// Cookies without a Max-age or Expires attribute – are deleted when the current session ends
170+
// and some browsers use session restoring when restarting. This can cause session cookies to last indefinitely.
171+
MaxAge: time.Hour * 24,
172+
},
173+
})
174+
130175
// Create a new store instance and attach to session manager
131176
sessMan.UseStore(memory.New())
132-
// Register callbacks for read and write cookie
177+
// Register callbacks for read and write cookie.
133178
// Get cookie callback should get cookie based on cookie name and
134179
// sent back in net/http cookie format.
135-
sessMan.RegisterGetCookie(getCookie)
136180
// Set cookie callback should set cookie it received for received cookie name.
137-
sessMan.RegisterSetCookie(setCookie)
181+
sessMan.SetCookieHooks(getCookie, setCookie)
138182

139-
http.HandleFunc("/set", handler)
183+
// Initialize the handler.
184+
http.HandleFunc("/", handler)
140185
}
141186
```

TODO

Lines changed: 0 additions & 14 deletions
This file was deleted.

conv/conv.go

Lines changed: 0 additions & 187 deletions
This file was deleted.

0 commit comments

Comments
 (0)