# wisp_kv_sessions
[](https://hex.pm/packages/wisp_kv_sessions)
[](https://hexdocs.pm/wisp_kv_sessions/)
# Overview
wisp_kv_sessions is a key-value session management library for [Wisp](https://gleam-wisp.github.io/wisp/), inspired by the Rust crate [tower sessions](https://docs.rs/tower-sessions/latest/tower_sessions/#). This library allows you to manage user sessions with ease, storing session data in a simple key-value store.
# Example Usage
An minimal example usage is available in `./example/app.gleam`.
```gleam
import gleam/dynamic
import gleam/erlang/process
import gleam/json
import gleam/option
import gleam/result
import gleam/string_builder
import mist
import wisp
import wisp/wisp_mist
import wisp_kv_sessions
import wisp_kv_sessions/actor_store
import wisp_kv_sessions/session
import wisp_kv_sessions/session_config
pub fn main() {
// Setup session_store
use actor_store <- result.map(actor_store.try_create_session_store())
use cache_store <- result.map(actor_store.try_create_session_store())
// Create session config
let session_config =
session_config.Config(
default_expiry: session.ExpireIn(60 * 60),
cookie_name: "SESSION_COOKIE",
store: actor_store,
cache: option.Some(cache_store),
)
let secret_key_base = wisp.random_string(64)
// Start the Mist web server.
let assert Ok(_) =
wisp_mist.handler(handle_request(_, session_config), secret_key_base)
|> mist.new
|> mist.port(8000)
|> mist.start_http
process.sleep_forever()
}
pub fn handle_request(req: wisp.Request, session_config) -> wisp.Response {
use req <- wisp_kv_sessions.middleware(session_config, req)
case wisp.path_segments(req) {
[] -> get_value_page(req, session_config)
["set"] -> set_value_page(req, session_config)
_ -> wisp.not_found()
}
}
fn get_value_page(
req: wisp.Request,
session_config: session_config.Config,
) -> wisp.Response {
// Read value to the session
let assert Ok(key) =
wisp_kv_sessions.get(session_config, req, "test_key", dynamic.string)
case key {
option.Some(k) -> {
wisp.html_response(string_builder.from_string(k), 200)
}
option.None -> {
wisp.html_response(
string_builder.from_string("No value set. Go to /set to set a value"),
200,
)
}
}
}
// Not nessesary for this simple type
fn encode_string(str: String) {
json.string(str) |> json.to_string
}
fn set_value_page(
req: wisp.Request,
session_config: session_config.Config,
) -> wisp.Response {
// Set value to the session
let _ =
wisp_kv_sessions.set(
session_config,
req,
"test_key",
"something",
encode_string,
)
wisp.redirect("/")
}
```
## Running the Example
To start the server, cd into /example and run `gleam run`.
Visit (http://localhost:8000) in your browser. The page should display "No value set. Go to /set to set a value."
Navigate to (http://localhost:8000/set). You will be redirected back to the main page, which will now display "something".
# Development
```sh
gleam run # Run the project
gleam test # Run the tests
just watch-test # Run test and reload on file changes
```
# Caching
A session config can be passed an optional cache parameter that is a `SessionStore`
wrapped in an `option.Option`. If the cache is `option.Some` sessions will be
fetched from the cache. If the data is not in the cache the `store` will be
tried.
Session data will be automatically added and removed from the cache.
# SessionStore
A SessionStore is an type that can be used to implement different storage
providers, such as postgres/reddis/sqlite. You can use one of the prebuild
storage providers from down below, or implement a new one if the one you
are looking for does not exist.
For an example implementation, see `./src/wisp_kv_sessions/actor_store.gleam`.
## Existing SessionStores
### actor_store (Included by Default)
The actor_store driver is suitable for development and testing purposes,
but not recommended for production due to its non-concurrent nature.
Internally, it uses an [actor](https://hexdocs.pm/gleam_otp/gleam/otp/actor.html),
which may become a bottleneck under heavy loads.
*Usage Example:*
```gleam
import wisp_kv_sessions/actor_store
use session_store <- result.map(actor_store.try_create_session_store())
// ...
```
See `./example/src/app.gleam` for full example
### postgress_store
The postgres_store uses a [gleam/pgo](https://hexdocs.pm/gleam_pgo/gleam/pgo.html)
connection to store the session information in postgres.
```sh
gleam add wisp_kv_sessions_postgres_store
```
```gleam
import wisp_kv_sessions/postgres_store
let db = pgo.connect(pgo.default_config())
// Migrate
use _ <- result.try(postgres_store.migrate_up(conn))
// Setup session_store
use session_store <- result.map(postgres_store.try_create_session_store(conn))
//...
```
Further documentation can be found at <https://hexdocs.pm/wisp_kv_sessions_postgres_store>.
### ets_store
The ets_store uses [Erlang Term Storage](https://www.erlang.org/doc/apps/stdlib/ets.html)
and [carpenter](https://hexdocs.pm/carpenter/) to store session information.
*This will NOT be persistant after restarts*. But is a good option for caching.
```sh
gleam add wisp_kv_sessions_ets_store
```
```gleam
import wisp_kv_sessions/ets_store
// Setup session_store
use session_store <- result.map(postgres_store.try_create_session_store(conn))
//...
```
Further documentation can be found at <https://hexdocs.pm/wisp_kv_sessions_ets_store>.