wisp_kv_sessions

Package Version Hex Docs

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.

Search Document