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
//! 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 otherwise invalid. When a valid, known
//! cookie is received in a request, the session is hydrated from this cookie.
//! The middleware leverages [`http::Extensions`](axum::http::Extensions) to
//! attach an [`async_session::Session`] to the request. Request handlers can
//! then interact with the session.
//!
//! # Example
//!
//! Using the middleware with axum is straightforward:
//!
//! ```rust,no_run
//! use axum::{routing::get, Extension, Router};
//! use axum_sessions::{
//! async_session::{MemoryStore, Session},
//! 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(Extension(session): Extension<Session>) {
//! // Use the session in your handler...
//! }
//!
//! 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:
//!
//! ```rust
//! use std::convert::Infallible;
//!
//! use axum::http::header::SET_COOKIE;
//! use axum_sessions::SessionLayer;
//! use http::{Request, Response};
//! use hyper::Body;
//! use tower::{Service, ServiceBuilder, ServiceExt};
//!
//! async fn handle(request: Request<Body>) -> Result<Response<Body>, Infallible> {
//! assert!(request
//! .extensions()
//! .get::<async_session::Session>()
//! .is_some());
//! Ok(Response::new(Body::empty()))
//! }
//!
//! # #[tokio::main]
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let store = async_session::MemoryStore::new();
//! let secret: Vec<u8> = ["_"]
//! .iter()
//! .cycle()
//! .take(64)
//! .flat_map(|s| s.as_bytes().to_owned())
//! .collect();
//! 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(())
//! # }
//! ```
mod session;
pub use async_session;
pub use axum_extra::extract::cookie::SameSite;
pub use self::session::{Session, SessionLayer};