App state in Actix-web

App state in Actix-web
State can be accessed with the web::Data<T> extractor where T is the type of the state

AppState 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
}
Rust Programming

Next article

Rust Workspaces