App state in Actix-web

web::Data<T>
extractor where T
is the type of the stateAppState provides a clean, type-safe mechanism for sharing crucial resources like database connections, configuration settings, and caches across your application’s request handlers. Without it, developers would need to repeatedly establish database connections or reload configurations for each request, dramatically reducing performance and increasing complexity. By leveraging Actix-web’s AppState pattern, you create more maintainable, efficient, and scalable web applications with proper separation of concerns.
Understanding App State
This Actix-Web Rust server handles messages and tracks server status. It shares state using Mutex
-protected HashMap
and String
. Clients can GET
or POST
a message and GET
a list of servers. State is initialized in main
and injected into request handlers for simple thread-safe access.
.app_data(web::Data::new(AppState {...
use actix_web::{App, HttpResponse, HttpServer, web};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Mutex;
#[derive(Serialize, Deserialize)]
struct Message {
content: String,
}
#[derive(Serialize, Clone)]
struct Server {
name: String,
status: String,
}
// shared application state
struct AppState {
// Use a regular Mutex for simplicity
servers: Mutex<HashMap<String, Server>>,
// For a simple version, we'll just keep the last message
last_message: Mutex<String>,
}
// Handle GET requests to /message
async fn get_message(data: web::Data<AppState>) -> HttpResponse {
let message = data.last_message.lock().unwrap().clone();
HttpResponse::Ok().json(Message { content: message })
}
// Handle POST requests to /message
async fn post_message(msg: web::Json<Message>, data: web::Data<AppState>) -> HttpResponse {
// Store the message
let mut last_message = data.last_message.lock().unwrap();
*last_message = msg.content.clone();
// Return success response
HttpResponse::Ok().body("Message received")
}
// List all servers
async fn list_servers(data: web::Data<AppState>) -> HttpResponse {
let servers = data.servers.lock().unwrap();
let server_list: Vec<_> = servers.values().cloned().collect();
HttpResponse::Ok().json(server_list)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Starting simple message server...");
// Initialize our state
let mut server_map = HashMap::new();
server_map.insert(
"server1".to_string(),
Server {
name: "Demo Server".to_string(),
status: "Online".to_string(),
},
);
let state = web::Data::new(AppState {
servers: Mutex::new(server_map),
last_message: Mutex::new("No messages yet".to_string()),
});
HttpServer::new(move || {
App::new()
.app_data(state.clone())
.route("/message", web::get().to(get_message))
.route("/message", web::post().to(post_message))
.route("/servers", web::get().to(list_servers))
})
.bind("127.0.0.1:8000")?
.run()
.await
}