1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
//! axum-sessions is a middleware providing cookie-based sessions for axum
//! applications.
//!
//! [`SessionLayer`] provides client sessions via [`async_session`]. Sessions
//! are backed by cryptographically signed cookies. These cookies are generated
//! when they're not found or are otherwise invalid. When a valid, known cookie
//! is received in a request, the session is hydrated from this cookie. The
//! middleware provides sessions via [`SessionHandle`]. Handlers use the
//! [`ReadableSession`](crate::extractors::ReadableSession) and
//! [`WritableSession`](crate::extractors::WritableSession) extractors to read
//! from and write to sessions respectively.
//!
//! # Example
//!
//! Using the middleware with axum is straightforward:
//!
//! ```rust,no_run
//! use axum::{routing::get, Router};
//! use axum_sessions::{
//! async_session::MemoryStore, extractors::WritableSession, PersistencePolicy, SessionLayer,
//! };
//!
//! #[tokio::main]
//! async fn main() {
//! let store = async_session::MemoryStore::new();
//! let secret = b"..."; // MUST be at least 64 bytes!
//! let session_layer = SessionLayer::new(store, secret);
//!
//! async fn handler(mut session: WritableSession) {
//! session
//! .insert("foo", 42)
//! .expect("Could not store the answer.");
//! }
//!
//! let app = Router::new().route("/", get(handler)).layer(session_layer);
//!
//! axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
//! .serve(app.into_make_service())
//! .await
//! .unwrap();
//! }
//! ```
//!
//! This middleware may also be used as a generic Tower middleware by making use
//! of the [`SessionHandle`] extension:
//!
//! ```rust
//! use std::convert::Infallible;
//!
//! use axum::http::header::SET_COOKIE;
//! use axum_sessions::{SessionHandle, SessionLayer};
//! use http::{Request, Response};
//! use hyper::Body;
//! use rand::Rng;
//! use tower::{Service, ServiceBuilder, ServiceExt};
//!
//! async fn handle(request: Request<Body>) -> Result<Response<Body>, Infallible> {
//! let session_handle = request.extensions().get::<SessionHandle>().unwrap();
//! let session = session_handle.read().await;
//! // Use the session as you'd like.
//!
//! Ok(Response::new(Body::empty()))
//! }
//!
//! # #[tokio::main]
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let store = async_session::MemoryStore::new();
//! let secret = rand::thread_rng().gen::<[u8; 128]>();
//! let session_layer = SessionLayer::new(store, &secret);
//!
//! let mut service = ServiceBuilder::new()
//! .layer(session_layer)
//! .service_fn(handle);
//!
//! let request = Request::builder().body(Body::empty()).unwrap();
//!
//! let response = service.ready().await?.call(request).await?;
//!
//! assert_eq!(
//! response
//! .headers()
//! .get(SET_COOKIE)
//! .unwrap()
//! .to_str()
//! .unwrap()
//! .split("=")
//! .collect::<Vec<_>>()[0],
//! "axum.sid"
//! );
//!
//! # Ok(())
//! # }
//! ```
#![deny(missing_docs)]
pub mod extractors;
mod session;
pub use async_session;
pub use axum_extra::extract::cookie::SameSite;
pub use self::session::{PersistencePolicy, Session, SessionHandle, SessionLayer};