Getting Started with Actix

Prerequisites

Before you begin, ensure you have the following installed:

  • Rust (latest stable version)
  • Cargo (comes with Rust)

Setting Up Your Project

Create a new Rust project using Cargo:

cargo new actix_chat
cd actix_chat

Next, add Actix dependencies in your Cargo.toml:

[dependencies]
actix-web = "4.0"
actix-rt = "2.5"
tokio = { version = "1.0", features = ["full"] }

Building the Basic Server

Now, let’s create a simple HTTP server using Actix. Open src/main.rs and replace its content with the following code:

use actix_web::{web, App, HttpServer, Responder};

async fn greet() -> impl Responder {
    "Welcome to the Actix Chat Server!"
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(greet))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Running the Server

To run your server, execute:

cargo run

You should see output indicating that the server is running. Visit http://127.0.0.1:8080 in your web browser, and you should see the welcome message.

Implementing WebSocket for Real-time Communication

To create a real-time chat application, we need to implement WebSocket support. First, update your dependencies in Cargo.toml to include the actix-web-actors package:

[dependencies]
actix-web = "4.0"
actix-rt = "2.5"
actix-web-actors = "4.0"
tokio = { version = "1.0", features = ["full"] }

Creating a WebSocket Handler

Now, let’s create a WebSocket handler. Add the following code to src/main.rs:

use actix_web::{web, App, HttpServer, Responder, HttpRequest};
use actix_web_actors::ws;

struct ChatSession;

impl ws::MessageHandler<ChatSession> for ChatSession {
    fn handle(&mut self, msg: ws::Message, ctx: &mut ws::WebsocketContext<Self>) {
        match msg {
            ws::Message::Text(text) => {
                ctx.text(text);
            }
            _ => (),
        }
    }
}

async fn websocket_handler(req: HttpRequest, stream: web::Payload) -> Result<ws::WebsocketResponse<ChatSession>, actix_web::Error> {
    ws::start(ChatSession {}, &req, stream)
}

Updating the Server to Handle WebSocket Connections

Next, update the server to include a route for WebSocket connections. Modify the main function as follows:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(greet))
            .route("/ws/", web::get().to(websocket_handler))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Testing the WebSocket Connection

To test the WebSocket connection, you can use a simple HTML client. Create a new file named index.html in the project root with the following content:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Actix Chat</title>
</head>
<body>
    <h1>Actix Chat</h1>
    <input id="message" type="text" placeholder="Type a message...">
    <button onclick="sendMessage()">Send</button>
    <ul id="messages"></ul>

    <script>
        const socket = new WebSocket("ws://127.0.0.1:8080/ws/");

        socket.onmessage = function(event) {
            const messages = document.getElementById("messages");
            const message = document.createElement("li");
            message.textContent = event.data;
            messages.appendChild(message);
        };

        function sendMessage() {
            const input = document.getElementById("message");
            socket.send(input.value);
            input.value = '';
        }
    </script>
</body>
</html>

Serve this HTML file using a simple HTTP server, or open it directly in your browser. You can now send messages through the WebSocket connection, and they will be echoed back.

Conclusion

In this tutorial, we built a simple real-time chat application using the Actix framework in Rust. We covered setting up a basic HTTP server, implementing WebSocket support for real-time communication, and creating a simple HTML client to interact with our server.

By leveraging Actix, you can build efficient and scalable real-time applications in Rust, taking full advantage of its performance and safety features.

Learn more with useful resources