1
0
mirror of https://github.com/actix/actix-website synced 2024-11-30 19:14:36 +01:00

Update App State documentation

This commit is contained in:
Katherine Philip 2019-07-15 16:35:50 +07:00
parent 093852e4dc
commit 4521375534
2 changed files with 46 additions and 32 deletions

View File

@ -43,30 +43,33 @@ as the first application, it would match all incoming requests.
## State ## State
Application state is shared with all routes and resources within the same scope. State Application state is shared with all routes and resources within the same scope. State
can be accessed with the `web::Data<State>` extractor as read-only, but interior mutability with can be accessed with the `web::Data<State>` extractor. State is also available for route matching guards and middlewares.
`Cell` can be used to achieve state mutability. State is also available for route
matching guards and middlewares.
Let's write a simple application that uses shared state. We are going to store request count Let's write a simple application and store the application name in the state:
in the state:
{{< include-example example="application" file="state.rs" section="setup" >}} {{< include-example example="application" file="state.rs" section="setup" >}}
When the app is initialized it needs to be passed the initial state: and pass in the state when initializing the App, and start the application:
{{< include-example example="application" file="state.rs" section="make_app" >}}
> **Note**: `HttpServer` accepts an application factory rather than an application
> instance. `HttpServer` constructs an application instance for each thread, thus
> application state must be constructed multiple times. If you want to share state between
> different threads, a shared object should be used, e.g. `Arc`. There is also an
> [Example][stateexample] using `Arc` for this. Application state does not need to be
> `Send` and `Sync`, but the application factory must be `Send` + `Sync`.
To start the previous app, create it into a closure:
{{< include-example example="application" file="state.rs" section="start_app" >}} {{< include-example example="application" file="state.rs" section="start_app" >}}
## Shared Mutable State
`HttpServer` accepts an application factory rather than an application instance.
Http server constructs an application instance for each thread, thus application data must be
constructed multiple times. If you want to share data between different threads, a shareable
object should be used, e.g. Send + Sync.
Internally, `web::Data` uses Arc. Thus, in order to avoid double Arc, we should create our Data before registering it using `register_data()`.
In the following example, we will write an application with mutable, shared state. First, we define our state and create our handler:
{{< include-example example="application" file="state.rs" section="setup_mutable" >}}
and initialize in in an App:
{{< include-example example="application" file="state.rs" section="make_app_mutable" >}}
## Combining applications with different state ## Combining applications with different state
Combining multiple applications with different state is possible as well. Combining multiple applications with different state is possible as well.

View File

@ -1,42 +1,53 @@
// <setup> // <setup>
use actix_web::{web, App, HttpServer}; use actix_web::{web, App, HttpServer};
use std::cell::Cell;
// This struct represents state // This struct represents state
struct AppState { struct AppState {
counter: Cell<i32>, app_name: String,
} }
fn index(data: web::Data<AppState>) -> String { fn index(data: web::Data<AppState>) -> String {
let count = data.counter.get() + 1; // <- get count let app_name = data.app_name; // <- get app_name
data.counter.set(count); // <- store new count in state
format!("Request number: {}", count) // <- response with count format!("Hello {}!", app_name) // <- response with app_name
} }
// </setup> // </setup>
// <make_app> // <setup_mutable>
struct AppStateWithCounter {
counter: Mutex<i32>, // <- Mutex is necessary to mutate safely across threads
}
fn _index(data: web::Data<AppStateWithCounter>) -> String {
let mut counter = state.counter.lock().unwrap(); // <- get counter's MutexGuard
*counter += 1; // <- access counter inside MutexGuard
format!("Request number: {}", counter) // <- response with count
}
// </setup_mutable>
// <make_app_mutable>
fn _main() { fn _main() {
let counter = web::Data::new(AppStateWithCounter { counter : Mutex::new(0)});
App::new() App::new()
.data(AppState { .register_data(counter.clone()) // <- register the created data
counter: Cell::new(0),
})
.route("/", web::get().to(index)); .route("/", web::get().to(index));
} }
// </make_app> // </make_app_mutable>
// <start_app> // <start_app>
pub fn main() { pub fn main() {
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
.data(AppState { .data(AppState {
counter: Cell::new(0), app_name: String::from("Actix-web")
}) })
.route("/", web::get().to(index)) .route("/", web::get().to(index))
}) })
.bind("127.0.0.1:8088") .bind("127.0.0.1:8088")
.unwrap() .unwrap()
.run() .run()
.unwrap(); .unwrap();
} }
// </start_app> // </start_app>