wisp_kv_sessions
Overview
wisp_kv_sessions is a key-value session management library for Wisp, inspired by the Rust crate 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
.
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
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, which may become a bottleneck under heavy loads.
Usage Example:
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 connection to store the session information in postgres.
gleam add wisp_kv_sessions_postgres_store
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 and carpenter to store session information. This will NOT be persistant after restarts. But is a good option for caching.
gleam add wisp_kv_sessions_ets_store
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.