1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +01:00

chore(actix-session): prepare release 0.9.0

This commit is contained in:
Rob Ede 2024-01-11 04:27:56 +00:00
parent 5ceb3c72cd
commit 8b4e8ea34e
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
10 changed files with 466 additions and 244 deletions

View File

@ -25,14 +25,14 @@
//! async fn main() -> std::io::Result<()> { //! async fn main() -> std::io::Result<()> {
//! HttpServer::new(|| { //! HttpServer::new(|| {
//! let cors = Cors::default() //! let cors = Cors::default()
//! .allowed_origin("https://www.rust-lang.org") //! .allowed_origin("https://www.rust-lang.org")
//! .allowed_origin_fn(|origin, _req_head| { //! .allowed_origin_fn(|origin, _req_head| {
//! origin.as_bytes().ends_with(b".rust-lang.org") //! origin.as_bytes().ends_with(b".rust-lang.org")
//! }) //! })
//! .allowed_methods(vec!["GET", "POST"]) //! .allowed_methods(vec!["GET", "POST"])
//! .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT]) //! .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
//! .allowed_header(http::header::CONTENT_TYPE) //! .allowed_header(http::header::CONTENT_TYPE)
//! .max_age(3600); //! .max_age(3600);
//! //!
//! App::new() //! App::new()
//! .wrap(cors) //! .wrap(cors)

View File

@ -19,7 +19,7 @@ all-features = true
[dependencies] [dependencies]
actix-service = "2" actix-service = "2"
actix-session = "0.8" actix-session = "0.9"
actix-utils = "3" actix-utils = "3"
actix-web = { version = "4", default-features = false, features = ["cookies", "secure-cookies"] } actix-web = { version = "4", default-features = false, features = ["cookies", "secure-cookies"] }
@ -31,7 +31,7 @@ tracing = { version = "0.1.30", default-features = false, features = ["log"] }
[dev-dependencies] [dev-dependencies]
actix-http = "3" actix-http = "3"
actix-web = { version = "4", default-features = false, features = ["macros", "cookies", "secure-cookies"] } actix-web = { version = "4", default-features = false, features = ["macros", "cookies", "secure-cookies"] }
actix-session = { version = "0.8", features = ["redis-rs-session", "cookie-session"] } actix-session = { version = "0.9", features = ["redis-rs-session", "cookie-session"] }
env_logger = "0.10" env_logger = "0.10"
reqwest = { version = "0.11", default-features = false, features = ["cookies", "json"] } reqwest = { version = "0.11", default-features = false, features = ["cookies", "json"] }

View File

@ -11,7 +11,94 @@
<!-- prettier-ignore-end --> <!-- prettier-ignore-end -->
## Documentation & community resources <!-- cargo-rdme start -->
- [API Documentation](https://docs.rs/actix-identity) Identity management for Actix Web.
- Minimum Supported Rust Version (MSRV): 1.57
`actix-identity` can be used to track identity of a user across multiple requests. It is built on top of HTTP sessions, via [`actix-session`](https://docs.rs/actix-session).
## Getting started
To start using identity management in your Actix Web application you must register [`IdentityMiddleware`] and `SessionMiddleware` as middleware on your `App`:
```rust
use actix_web::{cookie::Key, App, HttpServer, HttpResponse};
use actix_identity::IdentityMiddleware;
use actix_session::{storage::RedisSessionStore, SessionMiddleware};
#[actix_web::main]
async fn main() {
// When using `Key::generate()` it is important to initialize outside of the
// `HttpServer::new` closure. When deployed the secret key should be read from a
// configuration file or environment variables.
let secret_key = Key::generate();
let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379")
.await
.unwrap();
HttpServer::new(move || {
App::new()
// Install the identity framework first.
.wrap(IdentityMiddleware::default())
// The identity system is built on top of sessions. You must install the session
// middleware to leverage `actix-identity`. The session middleware must be mounted
// AFTER the identity middleware: `actix-web` invokes middleware in the OPPOSITE
// order of registration when it receives an incoming request.
.wrap(SessionMiddleware::new(
redis_store.clone(),
secret_key.clone()
))
// Your request handlers [...]
})
}
```
User identities can be created, accessed and destroyed using the [`Identity`] extractor in your request handlers:
```rust
use actix_web::{get, post, HttpResponse, Responder, HttpRequest, HttpMessage};
use actix_identity::Identity;
use actix_session::storage::RedisSessionStore;
#[get("/")]
async fn index(user: Option<Identity>) -> impl Responder {
if let Some(user) = user {
format!("Welcome! {}", user.id().unwrap())
} else {
"Welcome Anonymous!".to_owned()
}
}
#[post("/login")]
async fn login(request: HttpRequest) -> impl Responder {
// Some kind of authentication should happen here
// e.g. password-based, biometric, etc.
// [...]
// attach a verified user identity to the active session
Identity::login(&request.extensions(), "User1".into()).unwrap();
HttpResponse::Ok()
}
#[post("/logout")]
async fn logout(user: Identity) -> impl Responder {
user.logout();
HttpResponse::Ok()
}
```
## Advanced configuration
By default, `actix-identity` does not automatically log out users. You can change this behaviour by customising the configuration for [`IdentityMiddleware`] via [`IdentityMiddleware::builder`].
In particular, you can automatically log out users who:
- have been inactive for a while (see [`IdentityMiddlewareBuilder::visit_deadline`];
- logged in too long ago (see [`IdentityMiddlewareBuilder::login_deadline`]).
[`IdentityMiddlewareBuilder::visit_deadline`]: config::IdentityMiddlewareBuilder::visit_deadline
[`IdentityMiddlewareBuilder::login_deadline`]: config::IdentityMiddlewareBuilder::login_deadline
<!-- cargo-rdme end -->

View File

@ -1,90 +1,96 @@
//! Identity management for Actix Web. /*!
//! Identity management for Actix Web.
//! `actix-identity` can be used to track identity of a user across multiple requests. It is built
//! on top of HTTP sessions, via [`actix-session`](https://docs.rs/actix-session). `actix-identity` can be used to track identity of a user across multiple requests. It is built
//! on top of HTTP sessions, via [`actix-session`](https://docs.rs/actix-session).
//! # Getting started
//! To start using identity management in your Actix Web application you must register # Getting started
//! [`IdentityMiddleware`] and `SessionMiddleware` as middleware on your `App`: To start using identity management in your Actix Web application you must register
//! [`IdentityMiddleware`] and `SessionMiddleware` as middleware on your `App`:
//! ```no_run
//! # use actix_web::web; ```no_run
//! use actix_web::{cookie::Key, App, HttpServer, HttpResponse}; # use actix_web::web;
//! use actix_identity::IdentityMiddleware; use actix_web::{cookie::Key, App, HttpServer, HttpResponse};
//! use actix_session::{storage::RedisSessionStore, SessionMiddleware}; use actix_identity::IdentityMiddleware;
//! use actix_session::{storage::RedisSessionStore, SessionMiddleware};
//! #[actix_web::main]
//! async fn main() { #[actix_web::main]
//! let secret_key = Key::generate(); async fn main() {
//! let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379") // When using `Key::generate()` it is important to initialize outside of the
//! .await // `HttpServer::new` closure. When deployed the secret key should be read from a
//! .unwrap(); // configuration file or environment variables.
//! let secret_key = Key::generate();
//! HttpServer::new(move || {
//! App::new() let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379")
//! // Install the identity framework first. .await
//! .wrap(IdentityMiddleware::default()) .unwrap();
//! // The identity system is built on top of sessions. You must install the session
//! // middleware to leverage `actix-identity`. The session middleware must be mounted HttpServer::new(move || {
//! // AFTER the identity middleware: `actix-web` invokes middleware in the OPPOSITE App::new()
//! // order of registration when it receives an incoming request. // Install the identity framework first.
//! .wrap(SessionMiddleware::new( .wrap(IdentityMiddleware::default())
//! redis_store.clone(), // The identity system is built on top of sessions. You must install the session
//! secret_key.clone() // middleware to leverage `actix-identity`. The session middleware must be mounted
//! )) // AFTER the identity middleware: `actix-web` invokes middleware in the OPPOSITE
//! // Your request handlers [...] // order of registration when it receives an incoming request.
//! # .default_service(web::to(|| HttpResponse::Ok())) .wrap(SessionMiddleware::new(
//! }) redis_store.clone(),
//! # ; secret_key.clone(),
//! } ))
//! ``` // Your request handlers [...]
//! # .default_service(web::to(|| HttpResponse::Ok()))
//! User identities can be created, accessed and destroyed using the [`Identity`] extractor in your })
//! request handlers: # ;
//! }
//! ```no_run ```
//! use actix_web::{get, post, HttpResponse, Responder, HttpRequest, HttpMessage};
//! use actix_identity::Identity; User identities can be created, accessed and destroyed using the [`Identity`] extractor in your
//! use actix_session::storage::RedisSessionStore; request handlers:
//!
//! #[get("/")] ```no_run
//! async fn index(user: Option<Identity>) -> impl Responder { use actix_web::{get, post, HttpResponse, Responder, HttpRequest, HttpMessage};
//! if let Some(user) = user { use actix_identity::Identity;
//! format!("Welcome! {}", user.id().unwrap()) use actix_session::storage::RedisSessionStore;
//! } else {
//! "Welcome Anonymous!".to_owned() #[get("/")]
//! } async fn index(user: Option<Identity>) -> impl Responder {
//! } if let Some(user) = user {
//! format!("Welcome! {}", user.id().unwrap())
//! #[post("/login")] } else {
//! async fn login(request: HttpRequest) -> impl Responder { "Welcome Anonymous!".to_owned()
//! // Some kind of authentication should happen here }
//! // e.g. password-based, biometric, etc. }
//! // [...]
//! #[post("/login")]
//! // attach a verified user identity to the active session async fn login(request: HttpRequest) -> impl Responder {
//! Identity::login(&request.extensions(), "User1".into()).unwrap(); // Some kind of authentication should happen here
//! // e.g. password-based, biometric, etc.
//! HttpResponse::Ok() // [...]
//! }
//! // attach a verified user identity to the active session
//! #[post("/logout")] Identity::login(&request.extensions(), "User1".into()).unwrap();
//! async fn logout(user: Identity) -> impl Responder {
//! user.logout(); HttpResponse::Ok()
//! HttpResponse::Ok() }
//! }
//! ``` #[post("/logout")]
//! async fn logout(user: Identity) -> impl Responder {
//! # Advanced configuration user.logout();
//! By default, `actix-identity` does not automatically log out users. You can change this behaviour HttpResponse::Ok()
//! by customising the configuration for [`IdentityMiddleware`] via [`IdentityMiddleware::builder`]. }
//! ```
//! In particular, you can automatically log out users who:
//! - have been inactive for a while (see [`IdentityMiddlewareBuilder::visit_deadline`]; # Advanced configuration
//! - logged in too long ago (see [`IdentityMiddlewareBuilder::login_deadline`]). By default, `actix-identity` does not automatically log out users. You can change this behaviour
//! by customising the configuration for [`IdentityMiddleware`] via [`IdentityMiddleware::builder`].
//! [`IdentityMiddlewareBuilder::visit_deadline`]: config::IdentityMiddlewareBuilder::visit_deadline
//! [`IdentityMiddlewareBuilder::login_deadline`]: config::IdentityMiddlewareBuilder::login_deadline In particular, you can automatically log out users who:
- have been inactive for a while (see [`IdentityMiddlewareBuilder::visit_deadline`];
- logged in too long ago (see [`IdentityMiddlewareBuilder::login_deadline`]).
[`IdentityMiddlewareBuilder::visit_deadline`]: config::IdentityMiddlewareBuilder::visit_deadline
[`IdentityMiddlewareBuilder::login_deadline`]: config::IdentityMiddlewareBuilder::login_deadline
*/
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![deny(rust_2018_idioms, nonstandard_style, missing_docs)] #![deny(rust_2018_idioms, nonstandard_style, missing_docs)]

View File

@ -32,7 +32,7 @@ redis = { version = "0.24", default-features = false, features = ["tokio-comp"]
time = "0.3" time = "0.3"
# session # session
actix-session = { version = "0.8", optional = true } actix-session = { version = "0.9", optional = true }
[dev-dependencies] [dev-dependencies]
actix-web = "4" actix-web = "4"

View File

@ -2,6 +2,8 @@
## Unreleased ## Unreleased
## 0.9.0
- Remove use of `async-trait` on `SessionStore` trait. - Remove use of `async-trait` on `SessionStore` trait.
- Minimum supported Rust version (MSRV) is now 1.75. - Minimum supported Rust version (MSRV) is now 1.75.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-session" name = "actix-session"
version = "0.8.0" version = "0.9.0"
authors = [ authors = [
"Nikolay Kim <fafhrd91@gmail.com>", "Nikolay Kim <fafhrd91@gmail.com>",
"Luca Palmieri <rust@lpalmieri.com>", "Luca Palmieri <rust@lpalmieri.com>",

View File

@ -5,14 +5,130 @@
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
[![crates.io](https://img.shields.io/crates/v/actix-session?label=latest)](https://crates.io/crates/actix-session) [![crates.io](https://img.shields.io/crates/v/actix-session?label=latest)](https://crates.io/crates/actix-session)
[![Documentation](https://docs.rs/actix-session/badge.svg?version=0.8.0)](https://docs.rs/actix-session/0.8.0) [![Documentation](https://docs.rs/actix-session/badge.svg?version=0.9.0)](https://docs.rs/actix-session/0.9.0)
![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/actix-session) ![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/actix-session)
[![Dependency Status](https://deps.rs/crate/actix-session/0.8.0/status.svg)](https://deps.rs/crate/actix-session/0.8.0) [![Dependency Status](https://deps.rs/crate/actix-session/0.9.0/status.svg)](https://deps.rs/crate/actix-session/0.9.0)
<!-- prettier-ignore-end --> <!-- prettier-ignore-end -->
## Documentation & Resources <!-- cargo-rdme start -->
- [API Documentation](https://docs.rs/actix-session) Session management for Actix Web.
- [Example Projects](https://github.com/actix/examples/tree/master/auth/cookie-session)
- Minimum Supported Rust Version (MSRV): 1.57 The HTTP protocol, at a first glance, is stateless: the client sends a request, the server parses its content, performs some processing and returns a response. The outcome is only influenced by the provided inputs (i.e. the request content) and whatever state the server queries while performing its processing.
Stateless systems are easier to reason about, but they are not quite as powerful as we need them to be - e.g. how do you authenticate a user? The user would be forced to authenticate **for every single request**. That is, for example, how 'Basic' Authentication works. While it may work for a machine user (i.e. an API client), it is impractical for a person—you do not want a login prompt on every single page you navigate to!
There is a solution - **sessions**. Using sessions the server can attach state to a set of requests coming from the same client. They are built on top of cookies - the server sets a cookie in the HTTP response (`Set-Cookie` header), the client (e.g. the browser) will store the cookie and play it back to the server when sending new requests (using the `Cookie` header).
We refer to the cookie used for sessions as a **session cookie**. Its content is called **session key** (or **session ID**), while the state attached to the session is referred to as **session state**.
`actix-session` provides an easy-to-use framework to manage sessions in applications built on top of Actix Web. [`SessionMiddleware`] is the middleware underpinning the functionality provided by `actix-session`; it takes care of all the session cookie handling and instructs the **storage backend** to create/delete/update the session state based on the operations performed against the active [`Session`].
`actix-session` provides some built-in storage backends: ([`CookieSessionStore`], [`RedisSessionStore`], and [`RedisActorSessionStore`]) - you can create a custom storage backend by implementing the [`SessionStore`] trait.
Further reading on sessions:
- [RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265);
- [OWASP's session management cheat-sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html).
## Getting started
To start using sessions in your Actix Web application you must register [`SessionMiddleware`] as a middleware on your `App`:
```rust
use actix_web::{web, App, HttpServer, HttpResponse, Error};
use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore};
use actix_web::cookie::Key;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// When using `Key::generate()` it is important to initialize outside of the
// `HttpServer::new` closure. When deployed the secret key should be read from a
// configuration file or environment variables.
let secret_key = Key::generate();
let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379")
.await
.unwrap();
HttpServer::new(move ||
App::new()
// Add session management to your application using Redis for session state storage
.wrap(
SessionMiddleware::new(
redis_store.clone(),
secret_key.clone(),
)
)
.default_service(web::to(|| HttpResponse::Ok())))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
```
The session state can be accessed and modified by your request handlers using the [`Session`] extractor. Note that this doesn't work in the stream of a streaming response.
```rust
use actix_web::Error;
use actix_session::Session;
fn index(session: Session) -> Result<&'static str, Error> {
// access the session state
if let Some(count) = session.get::<i32>("counter")? {
println!("SESSION value: {}", count);
// modify the session state
session.insert("counter", count + 1)?;
} else {
session.insert("counter", 1)?;
}
Ok("Welcome!")
}
```
## Choosing A Backend
By default, `actix-session` does not provide any storage backend to retrieve and save the state attached to your sessions. You can enable:
- a purely cookie-based "backend", [`CookieSessionStore`], using the `cookie-session` feature flag.
```toml
[dependencies]
# ...
actix-session = { version = "...", features = ["cookie-session"] }
```
- a Redis-based backend via [`actix-redis`](https://docs.rs/actix-redis), [`RedisActorSessionStore`], using the `redis-actor-session` feature flag.
```toml
[dependencies]
# ...
actix-session = { version = "...", features = ["redis-actor-session"] }
```
- a Redis-based backend via [`redis-rs`](https://docs.rs/redis-rs), [`RedisSessionStore`], using the `redis-rs-session` feature flag.
```toml
[dependencies]
# ...
actix-session = { version = "...", features = ["redis-rs-session"] }
```
Add the `redis-rs-tls-session` feature flag if you want to connect to Redis using a secured connection:
```toml
[dependencies]
# ...
actix-session = { version = "...", features = ["redis-rs-session", "redis-rs-tls-session"] }
```
You can implement your own session storage backend using the [`SessionStore`] trait.
[`SessionStore`]: storage::SessionStore
[`CookieSessionStore`]: storage::CookieSessionStore
[`RedisSessionStore`]: storage::RedisSessionStore
[`RedisActorSessionStore`]: storage::RedisActorSessionStore
<!-- cargo-rdme end -->

View File

@ -1,137 +1,145 @@
//! Session management for Actix Web. /*!
//! Session management for Actix Web.
//! The HTTP protocol, at a first glance, is stateless: the client sends a request, the server
//! parses its content, performs some processing and returns a response. The outcome is only The HTTP protocol, at a first glance, is stateless: the client sends a request, the server
//! influenced by the provided inputs (i.e. the request content) and whatever state the server parses its content, performs some processing and returns a response. The outcome is only
//! queries while performing its processing. influenced by the provided inputs (i.e. the request content) and whatever state the server
//! queries while performing its processing.
//! Stateless systems are easier to reason about, but they are not quite as powerful as we need them
//! to be - e.g. how do you authenticate a user? The user would be forced to authenticate **for Stateless systems are easier to reason about, but they are not quite as powerful as we need them
//! every single request**. That is, for example, how 'Basic' Authentication works. While it may to be - e.g. how do you authenticate a user? The user would be forced to authenticate **for
//! work for a machine user (i.e. an API client), it is impractical for a person—you do not want a every single request**. That is, for example, how 'Basic' Authentication works. While it may
//! login prompt on every single page you navigate to! work for a machine user (i.e. an API client), it is impractical for a personyou do not want a
//! login prompt on every single page you navigate to!
//! There is a solution - **sessions**. Using sessions the server can attach state to a set of
//! requests coming from the same client. They are built on top of cookies - the server sets a There is a solution - **sessions**. Using sessions the server can attach state to a set of
//! cookie in the HTTP response (`Set-Cookie` header), the client (e.g. the browser) will store the requests coming from the same client. They are built on top of cookies - the server sets a
//! cookie and play it back to the server when sending new requests (using the `Cookie` header). cookie in the HTTP response (`Set-Cookie` header), the client (e.g. the browser) will store the
//! cookie and play it back to the server when sending new requests (using the `Cookie` header).
//! We refer to the cookie used for sessions as a **session cookie**. Its content is called
//! **session key** (or **session ID**), while the state attached to the session is referred to as We refer to the cookie used for sessions as a **session cookie**. Its content is called
//! **session state**. **session key** (or **session ID**), while the state attached to the session is referred to as
//! **session state**.
//! `actix-session` provides an easy-to-use framework to manage sessions in applications built on
//! top of Actix Web. [`SessionMiddleware`] is the middleware underpinning the functionality `actix-session` provides an easy-to-use framework to manage sessions in applications built on
//! provided by `actix-session`; it takes care of all the session cookie handling and instructs the top of Actix Web. [`SessionMiddleware`] is the middleware underpinning the functionality
//! **storage backend** to create/delete/update the session state based on the operations performed provided by `actix-session`; it takes care of all the session cookie handling and instructs the
//! against the active [`Session`]. **storage backend** to create/delete/update the session state based on the operations performed
//! against the active [`Session`].
//! `actix-session` provides some built-in storage backends: ([`CookieSessionStore`],
//! [`RedisSessionStore`], and [`RedisActorSessionStore`]) - you can create a custom storage backend `actix-session` provides some built-in storage backends: ([`CookieSessionStore`],
//! by implementing the [`SessionStore`] trait. [`RedisSessionStore`], and [`RedisActorSessionStore`]) - you can create a custom storage backend
//! by implementing the [`SessionStore`] trait.
//! Further reading on sessions:
//! - [RFC6265](https://datatracker.ietf.org/doc/html/rfc6265); Further reading on sessions:
//! - [OWASP's session management cheat-sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html). - [RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265);
//! - [OWASP's session management cheat-sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html).
//! # Getting started
//! To start using sessions in your Actix Web application you must register [`SessionMiddleware`] # Getting started
//! as a middleware on your `App`: To start using sessions in your Actix Web application you must register [`SessionMiddleware`]
//! as a middleware on your `App`:
//! ```no_run
//! use actix_web::{web, App, HttpServer, HttpResponse, Error}; ```no_run
//! use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore}; use actix_web::{web, App, HttpServer, HttpResponse, Error};
//! use actix_web::cookie::Key; use actix_session::{Session, SessionMiddleware, storage::RedisSessionStore};
//! use actix_web::cookie::Key;
//! #[actix_web::main]
//! async fn main() -> std::io::Result<()> { #[actix_web::main]
//! // The secret key would usually be read from a configuration file/environment variables. async fn main() -> std::io::Result<()> {
//! let secret_key = Key::generate(); // When using `Key::generate()` it is important to initialize outside of the
//! let redis_connection_string = "127.0.0.1:6379"; // `HttpServer::new` closure. When deployed the secret key should be read from a
//! HttpServer::new(move || // configuration file or environment variables.
//! App::new() let secret_key = Key::generate();
//! // Add session management to your application using Redis for session state storage
//! .wrap( let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379")
//! SessionMiddleware::new( .await
//! RedisActorSessionStore::new(redis_connection_string), .unwrap();
//! secret_key.clone()
//! ) HttpServer::new(move ||
//! ) App::new()
//! .default_service(web::to(|| HttpResponse::Ok()))) // Add session management to your application using Redis for session state storage
//! .bind(("127.0.0.1", 8080))? .wrap(
//! .run() SessionMiddleware::new(
//! .await redis_store.clone(),
//! } secret_key.clone(),
//! ``` )
//! )
//! The session state can be accessed and modified by your request handlers using the [`Session`] .default_service(web::to(|| HttpResponse::Ok())))
//! extractor. Note that this doesn't work in the stream of a streaming response. .bind(("127.0.0.1", 8080))?
//! .run()
//! ```no_run .await
//! use actix_web::Error; }
//! use actix_session::Session; ```
//!
//! fn index(session: Session) -> Result<&'static str, Error> { The session state can be accessed and modified by your request handlers using the [`Session`]
//! // access the session state extractor. Note that this doesn't work in the stream of a streaming response.
//! if let Some(count) = session.get::<i32>("counter")? {
//! println!("SESSION value: {}", count); ```no_run
//! // modify the session state use actix_web::Error;
//! session.insert("counter", count + 1)?; use actix_session::Session;
//! } else {
//! session.insert("counter", 1)?; fn index(session: Session) -> Result<&'static str, Error> {
//! } // access the session state
//! if let Some(count) = session.get::<i32>("counter")? {
//! Ok("Welcome!") println!("SESSION value: {}", count);
//! } // modify the session state
//! ``` session.insert("counter", count + 1)?;
//! } else {
//! # Choosing A Backend session.insert("counter", 1)?;
//! }
//! By default, `actix-session` does not provide any storage backend to retrieve and save the state
//! attached to your sessions. You can enable: Ok("Welcome!")
//! }
//! - a purely cookie-based "backend", [`CookieSessionStore`], using the `cookie-session` feature ```
//! flag.
//! # Choosing A Backend
//! ```toml
//! [dependencies] By default, `actix-session` does not provide any storage backend to retrieve and save the state
//! # ... attached to your sessions. You can enable:
//! actix-session = { version = "...", features = ["cookie-session"] }
//! ``` - a purely cookie-based "backend", [`CookieSessionStore`], using the `cookie-session` feature
//! flag.
//! - a Redis-based backend via [`actix-redis`](https://docs.rs/actix-redis),
//! [`RedisActorSessionStore`], using the `redis-actor-session` feature flag. ```toml
//! [dependencies]
//! ```toml # ...
//! [dependencies] actix-session = { version = "...", features = ["cookie-session"] }
//! # ... ```
//! actix-session = { version = "...", features = ["redis-actor-session"] }
//! ``` - a Redis-based backend via [`actix-redis`](https://docs.rs/actix-redis),
//! [`RedisActorSessionStore`], using the `redis-actor-session` feature flag.
//! - a Redis-based backend via [`redis-rs`](https://docs.rs/redis-rs), [`RedisSessionStore`], using
//! the `redis-rs-session` feature flag. ```toml
//! [dependencies]
//! ```toml # ...
//! [dependencies] actix-session = { version = "...", features = ["redis-actor-session"] }
//! # ... ```
//! actix-session = { version = "...", features = ["redis-rs-session"] }
//! ``` - a Redis-based backend via [`redis-rs`](https://docs.rs/redis-rs), [`RedisSessionStore`], using
//! the `redis-rs-session` feature flag.
//! Add the `redis-rs-tls-session` feature flag if you want to connect to Redis using a secured
//! connection: ```toml
//! [dependencies]
//! ```toml # ...
//! [dependencies] actix-session = { version = "...", features = ["redis-rs-session"] }
//! # ... ```
//! actix-session = { version = "...", features = ["redis-rs-session", "redis-rs-tls-session"] }
//! ``` Add the `redis-rs-tls-session` feature flag if you want to connect to Redis using a secured
//! connection:
//! You can implement your own session storage backend using the [`SessionStore`] trait.
//! ```toml
//! [`SessionStore`]: storage::SessionStore [dependencies]
//! [`CookieSessionStore`]: storage::CookieSessionStore # ...
//! [`RedisSessionStore`]: storage::RedisSessionStore actix-session = { version = "...", features = ["redis-rs-session", "redis-rs-tls-session"] }
//! [`RedisActorSessionStore`]: storage::RedisActorSessionStore ```
You can implement your own session storage backend using the [`SessionStore`] trait.
[`SessionStore`]: storage::SessionStore
[`CookieSessionStore`]: storage::CookieSessionStore
[`RedisSessionStore`]: storage::RedisSessionStore
[`RedisActorSessionStore`]: storage::RedisActorSessionStore
*/
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![deny(rust_2018_idioms, nonstandard_style)] #![deny(rust_2018_idioms, nonstandard_style)]

View File

@ -2,13 +2,16 @@ _list:
@just --list @just --list
# Format workspace. # Format workspace.
fmt: fmt: update-readmes
cargo +nightly fmt cargo +nightly fmt
npx -y prettier --write $(fd --hidden --extension=yml --extension=md) npx -y prettier --write $(fd --hidden --extension=yml --extension=md)
# Update READMEs from crate root documentation. # Update READMEs from crate root documentation.
update-readmes: && fmt update-readmes:
cd ./actix-cors && cargo rdme --force cd ./actix-cors && cargo rdme --force
cd ./actix-session && cargo rdme --force
cd ./actix-identity && cargo rdme --force
npx -y prettier --write $(fd README.md)
# Document crates in workspace. # Document crates in workspace.
doc: doc: