package
0.0.1
Repository: https://github.com/volatiletech/abcweb.git
Documentation: pkg.go.dev

# README

ABCSessions

License GoDoc Go Report Card

Available Session Storers

  • Disk
  • Memory
  • Redis
  • Cookie

API Operations

Note, you should avoid mixing and matching API calls for key-value versus object. Stick to one mode for every app you generate (either simple sessions using key-value strings and the regular helpers or a custom sessions struct using the object helpers). This is the main API entry point (key-value or object API) to use.

Key-Value string API

These session API endpoints are ideal for apps that only require simple session strings to be stored and not a full custom sessions struct with a lot of differing variables and types.

// Set adds a key-value pair to your session. 
Set(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value string) error

// Get retrieves a key-value pair value stored in your session.
Get(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) (string, error)

// Del deletes a key-value pair from your session.
Del(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) error

// AddFlash adds a flash message key-value pair to your session.
AddFlash(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value string) error

// GetFlash retrieves a flash message key-value pair value stored in your session. 
// Note that flash messages are automatically deleted after being retrieved once.
GetFlash(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) (string, error)

Object API

These session API endpoints are ideal for apps that are best served with a sessions struct opposed to individual strings. This flexibility allows you to define your own custom sessions struct with a range of differing variable types. See examples for Object API usage.

// SetObj adds any object or variable to your session.
SetObj(overseer Overseer, w http.ResponseWriter, r *http.Request, value interface{}) error

// GetObj retrieves an object or variable stored in your session.
GetObj(overseer Overseer, w http.ResponseWriter, r *http.Request, value interface{}) error

// AddFlashObj adds an object as a flash message to your session.
AddFlashObj(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value interface{}) error

// GetFlashObj retrieves a object as a flash message stored in your session.
// Note that flash messages are automatically deleted after being retrieved once.
GetFlashObj(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, pointer interface{}) error

Overseer interface

The job of an Overseer is to interface with your storers and manage your session cookies. If you want to work with the session values you probably want to use the higher level API functions listed above, but if you want to work with the session directly you can use these overseer methods.

Resetter

The Overseer interface embeds the Resetter interface which defines the functions used to reset the expiries of your sessions. This is handled automatically by the ResetMiddleware and is not something that needs to be called directly.

// Set creates or updates a session with a raw value.
Set(w http.ResponseWriter, r *http.Request, value string) error

// Get the raw value stored in a session.
Get(w http.ResponseWriter, r *http.Request) (value string, err error)

// Delete a session and signal the browser to expire the session cookie.
Del(w http.ResponseWriter, r *http.Request) error

// Regenerate a new session ID for your session.
Regenerate(w http.ResponseWriter, r *http.Request) error

// SessionID returns the session ID for your session.
SessionID(w http.ResponseWriter, r *http.Request) (id string, err error)

Storer interface

In the case of session management, "keys" here are synonymous with session IDs. This is as lower level API and generally not used too much, because the above higher-level API functions call these functions. This can be used if you need to deal with the storer directly for whatever reason.

// All retrieves all keys in the store.
All() (keys []string, err error)

// Get retrieves the value stored against a specific key.
Get(key string) (value string, err error)

// Set a key-value pair in the store.
Set(key, value string) error

// Delete a key-value pair from the store.
Del(key string) error

// Reset the expiry of a key in the store.
ResetExpiry(key string) error

Available Overseers

// StorageOverseer is used for all server-side sessions (disk, memory, redis, etc).
NewStorageOverseer(opts CookieOptions, storer Storer) *StorageOverseer

//CookieOverseer is used for client-side only cookie sessions.
NewCookieOverseer(opts CookieOptions, secretKey [32]byte) *CookieOverseer

How does each Storer work?

Disk

Disk sessions store the session as a text file on disk. By default they store in the systems temp directory under a folder that is randomly generated when you generate your app using abcweb app generator command. The file names are the UUIDs of the session. Each time the file is accessed (using Get, Set, manually on disk, or by using the ResetMiddleware) it will reset the access time of the file, which will push back the expiration defined by maxAge. For example, if your maxAge is set to 1 week, and your cleanInterval is set to 2 hours, then every 2 hours the cleaner will find all disk sessions files that have not been accessed for over 1 week and delete them. If the user refreshes a website and you're using the ResetMiddleware then that 1 week timer will be reset. If your maxAge and cleanInterval is set to 0 then these disk session files will permanently persist, however the browser will still expire sessions depending on your cookieOptions maxAge configuration. In a typical (default) setup, cookieOptions will be set to maxAge 0 (expire on browser close), your DiskStorer maxAge will be set to 2 days, and your DiskStorer cleanInterval will be set to 1 hour.

Memory

Memory sessions are stored in memory in a mutex protected map[string]memorySession. The key to the map is the session ID and the memorySession stores the value and expiry of the session. The memory storer also has methods to start and stop a cleaner go routine that will delete expired sessions on an interval that is defined when creating the memory session storer (cleanInterval).

Redis

Redis sessions are stored in a Redis database. Different databases can be used by specifying a different database ID on creation of the storer. Redis handles session expiration automatically.

Cookie

The cookie storer is intermingled with the CookieOverseer, so to use it you must use the CookieOverseer instead of the StorageOverseer. Cookie sessions are stored in encrypted form (AES-GCM encrypted and base64 encoded) in the clients browser.

Middlewares

Sessions Middleware

The sessions.Middleware is a required component when using this sessions package. The sessions middleware converts the ResponseWriter that is being passed along to your controller into a response type. This type implements the ResponseWriter interface, but its implementation also takes care of writing the cookies in the response objects buffer. These cookies are created as a result of creating/deleting sessions using the sessions library.

Sessions ResetMiddleware

When using the sessions.ResetMiddleware it will reset the expiry of the session of the current user regardless of whether that session is being loaded or modified by your controller. This ensures that users navigating to pages that rely on no session activation (for example a simple about page) will keep their session alive.

Without this middleware, for all storers except the disk storer, your session will only reset the expiry when modifying the session (using a Set call). For the disk storer it will refresh on both a Set and a Get because it relies on file access time.

In the majority of cases the middleware is the best user-experience, and we highly recommend loading this middleware by default. You should load one instance of this middleware for each session overseer you are using.

Error types

If an API operation fails, and you would like to check if it failed due to no session existing (errNoSession type), or the key used in a map-key operation not existing (errNoMapKey type), you can check the error types using the following functions against the errors returned:

// errNoSession is a possible return value of Get and ResetExpiry
IsNoSessionError(err error) bool

// errNoMapKey is a possible return value of abcsessions.Get and abcsessions.GetFlash
// It indicates that the key-value map stored under a session did not have the 
// requested key
IsNoMapKeyError(err error) bool

Examples

Using object helpers

// A session struct you've defined. Can contain anything you like.
type MySession struct {
	Username string
	AccessLevel int
	...
}

err := SetObj(o, w, r, MySession{...})
var mySess MySession

err := GetObj(o, w, r, &mySess)
if IsNoSessionError(err) {
	fmt.Printf("No session found")
}

Using object flash helpers

// A flash struct you've defined. Can contain anything you like.
type FlashError struct {
	Error string
	Code int
}

err := AddFlashObj(o, w, r, "login", &FlashError{...})
var errorObj FlashError

err := GetFlashObj(o, w, r, "login", &errorObj)

Create an Overseer

cookieOverseer := NewCookieOverseer(NewCookieOptions(), []byte("secretkeyhere"))
// Uses default addr of localhost:6379
storer, err := NewDefaultRedisStorer("", "", 0)
if err != nil {
	panic(err)
}

redisOverseer := NewStorageOverseer(NewCookieOptions(), storer)
storer, _ := NewDefaultMemoryStorer()
memoryOverseer := NewStorageOverseer(NewCookieOptions(), storer)

// Start the cleaner go routine
memoryOverseer.StartCleaner()

Handling unexpected errors

// o == overseer instance
val, err := abcsessions.Get(o, w, r, "coolkid")
if err != nil {
	if IsNoSessionError(err) {
		// Maybe you want to redirect? Maybe you want to create a new session?
	} else if IsNoMapKeyError(err) {
		// "coolkid" key didn't exist. Maybe you want to create it?
	} else {
		// Something crazy happened. Panic? Attempt to fix it?
		if err := o.Del(w, r); err != nil {
			panic(err)
		}
	}
}

# Functions

AddFlash adds a flash message to the session that will be deleted when it is retrieved with GetFlash.
AddFlashObj adds a flash message to the session that will be deleted when it is retrieved with GetFlash.
Del is a JSON helper used for deleting keys from a key-value session values store.
Get is a JSON helper used for retrieving key-value session values.
GetFlash retrieves a flash message from the session then deletes it.
GetFlashObj unmarshals a flash message from the session into the users pointer then deletes it from the session.
GetObj is a JSON helper used for retrieving object or variable session values.
IsNoMapKeyError checks an error to see if it means that there was no session map key.
IsNoSessionError checks an error to see if it means that there was no session.
Middleware converts the ResponseWriter object to a sessionsResponseWriter for buffering cookies across session API requests.
NewCookieOptions gives healthy defaults for session cookies.
NewCookieOverseer creates an overseer from cookie options and a secret key for use in encryption.
NewDefaultDiskStorer returns a DiskStorer object with default values.
NewDefaultMemoryStorer returns a MemoryStorer object with default values.
NewDefaultRedisStorer takes a bind address of the Redis server host:port and returns a RedisStorer object with default values.
NewDiskStorer initializes and returns a new DiskStorer object.
NewMemoryStorer initializes and returns a new MemoryStorer object.
NewRedisStorer initializes and returns a new RedisStorer object.
NewStorageOverseer returns a new storage overseer.
Set is a JSON helper used for storing key-value session values.
SetObj is a JSON helper used for storing object or variable session values.

# Structs

CookieOptions for the session cookies themselves.
CookieOverseer oversees cookie operations that are encrypted and verified but does store all data client side which means it is a possible attack vector.
DiskStorer is a session storer implementation for saving sessions to disk.
MemoryStorer is a session storer implementation for saving sessions to memory.
RedisStorer is a session storer implementation for saving sessions to a Redis database.
StorageOverseer holds cookie related variables and a session storer.

# Interfaces

Overseer of session cookies.
Resetter has reset functions.
Storer provides methods to retrieve, add and delete sessions.