@hackage snaplet-scoped-session0.1.1

Modularised session state for Snaplets, in a Snaplet

Scoped sessions

This snaplet provides a convenient way to handle typed sessions in your snap application.

It uses lenses to separate your session state into smaller parts which can then be individually managed by nested snaplets. The session state is therefore separated and subsnaplets have no access to the full global session state.

Session management

Session management inside your application is done by a session Snaplet. The Snaplet is created using initSessionSnaplet and it expects a Manager as an argument. Usually you won't have to create this manager yourself, simply find a library function which provides you with one that suits your needs and drop it in there. As an example there is a in memory which you can create with the function initMemoryManager from Snap.Snaplet.Session.Scoped.InMemory. You can find more information on this particular manager in the section The InMemory Manager

The Manager typeclass

Managers are responsible for persisting the session state in whichever way he sees fit. Depending on your choice of manager therefore your session can be kept in memory or a database or persistent in files on the server. Furthermore the manager handles the connection to the client, which in most cases will be a session cookie.

Managers are parameterised by the state they can manage. It uses the TypeInType extension to define the internal state.

For some Managers this may be any type

instance Manager (MyManager a) where
    type Manages (MyManager a) = a -- any state

or a constrained type

instance Serialize a => Manager (MySerializingManager a) where
    type Manages (MySerializingManager a) = a

or even a concrete type

instance Manager MyCountingManager where
    type Manages MyCountingManager = Int

The InMemory Manager

Snap.Snaplet.Session.Scoped.InMemory defines a Manager which stores arbitrary server side session state in the form of in-memory Haskell data. Session tracking is done using a configurable cookie and sessions are automatically expired to free memory by a concurrent worker which cleans the session state.

An example of the configuration can be found in resources/devel.cfg. All values are optional.

Wiring the Application

In order to give your snaplets access to the session manager you have to specify how the manager snaplet can be reached from inside your application. This is done by implementing a typeclass called HasManager.

data MyApp = MyApp { _sessionSnaplet :: Snaplet MyManager, ... }

makeLenses ''MyApp

instance HasManager MyApp where
    type TheManager MyApp = MyManager
    toManager = subSnaplet sessionSnaplet

Then, for each subsnaplet which is to have access to a part of the state you have to implement AccessSession to define the substate a Snaplet has access to.

data Session = Session
    { _snapletA :: SnapletASession
    , _snapletB :: SnapletBSession
    }

makeLenses SessionState

instance AccessSession SnapletA where
    type GlobalSession SnapletA = SessionState
    type LocalSession SnapletA = SnapletASession
    accessSession = mkAccessSessionLens snapletA

instance AccessSession SnapletB where
    type GlobalSession SnapletB = SessionState
    type LocalSession SnapletB = SnapletBSession
    accessSession = mkAccessSessionLens snapletB