Expand description

Typed-session-axum is a middleware providing cookie-based sessions for axum applications.

SessionLayer provides client sessions via the typed_session crate. Sessions are backed by cookies. These cookies are generated when they are not found or are otherwise invalid. When a valid, known cookie is received in a request, the session data is retrieved from the session store using this cookie.

The middleware provides sessions via SessionHandle. Handlers use the ReadableSession and WritableSession extractors to read from and write to sessions respectively.

The middleware expects a SessionStoreConnection to be present, which represents a connection to a database used to store the sessions. See SessionLayer::new for more details.

Example

Using the middleware with axum is straightforward:

use axum::{routing::get, Router, error_handling::HandleErrorLayer, Extension};
use tower::ServiceBuilder;
use typed_session_axum::{
    typed_session::{MemoryStore, NoLogger}, WritableSession, SessionLayer, SessionLayerError,
};
use std::fmt::Display;
use tokio::net::TcpListener;
use http::StatusCode;

#[tokio::main]
async fn main() {
    let store = MemoryStore::<i32, _>::new(); // mock database connection for debugging purposes
    let session_layer = SessionLayer::<i32, MemoryStore<i32, NoLogger>>::new();

    async fn handler(mut session: WritableSession<i32>) {
        *session.data_mut() = 42;
    }

    async fn error_handler<SessionStoreConnectorError: Display, InnerError: Display>(
        error: SessionLayerError<SessionStoreConnectorError, InnerError>
    ) -> (StatusCode, String) {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Error: {error}"),
        )   
    }

    let app = Router::new().route("/", get(handler)).layer(
        ServiceBuilder::new()
            .layer(HandleErrorLayer::new(error_handler)) // handle errors
            .layer(session_layer)
            .layer(Extension(store)) // provide a connection to the session database
    );

    let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

This middleware may also be used as a generic Tower middleware by making use of the SessionHandle extension:

use std::convert::Infallible;

use axum::http::header::SET_COOKIE;
use typed_session_axum::{typed_session::{MemoryStore, NoLogger}, SessionHandle, SessionLayer};
use http::{Request, Response};
use rand::Rng;
use tower::{Service, ServiceBuilder, ServiceExt};

async fn handle<Body: Default>(request: Request<Body>) -> Result<Response<Body>, Infallible> {
    let session_handle = request.extensions().get::<SessionHandle<()>>().unwrap();
    let mut session = session_handle.write().await;
    // Use the session as you'd like.
    session.data_mut();

    Ok(Response::new(Default::default()))
}

let store = MemoryStore::<(), _>::new(); // mock database connection for debugging purposes
let session_layer = SessionLayer::<(), MemoryStore<(), NoLogger>>::new();

let mut service = ServiceBuilder::new()
    .layer(session_layer)
    .service_fn(handle);

let mut request = Request::builder().body(String::new()).unwrap();
request.extensions_mut().insert(store); // provide a connection to the session database

let response = service.ready().await?.call(request).await?;

assert!(
    response
        .headers()
        .get(SET_COOKIE)
        .unwrap()
        .to_str()
        .unwrap()
        .starts_with("id=")
);

Re-exports

Structs

  • An extractor which provides a readable session. A single session may have many readers at the same time, but while a writer exists, no other reader or writer can exist.
  • Layer that provides cookie-based sessions. See SessionLayer::new for more details.
  • An extractor which provides a writable session. Note that this provides an exclusive (mutable) reference to the session associated with the HTTP request. If two HTTP requests are made with the same session id, the session may be altered by both requests at the same time, resulting in conflicts in the session store. In this case, the session layer produces an error that needs to be handled.

Enums

Type Aliases

  • A type alias which provides a handle to the underlying session.