Building a Simple Web Server in Rust Using Actix-web
Introduction
Rust has been making waves in the programming world for its focus on safety, speed, and concurrency. There is a reason why it has been the most loved programming language 8 years in a row on StackOverflow.
It’s a language designed to improve upon some of the shortcomings of C and C++ while providing modern features. One area where Rust is gaining traction is web development, and one of the prominent frameworks in this space is Actix-web. In this blog, we’ll explore how to build a simple web server using Rust and Actix-web, complete with user data handling.
We will be building a very simple web server with two routes as exemplar:
1. /
: an entrypoint into every programming language has been used as the base example of a get route which will respond with a “Hello world!”
2. /users/{user_id}
: A simple get route which fetches users from a constant list defined as a constant
Why Rust?
Rust was chosen for several reasons:
- Safety: Rust’s strict compile-time checks help prevent common bugs and security vulnerabilities such as null pointer dereferencing and buffer overflows.
- Performance: Rust’s performance is on par with C and C++ due to its lack of runtime overhead.
- Concurrency: Rust’s ownership model naturally prevents data races, making it easier to write concurrent programs.
Why Actix-web?
Actix-web is a powerful, pragmatic, and extremely fast web framework for Rust. Here’s why Actix-web is a great choice:
- Performance: Actix-web is known for its high performance and has been benchmarked as one of the fastest web frameworks.
- Asynchronous: Built on top of the Actix actor framework, it supports asynchronous request handling out of the box.
- Feature-rich: Actix-web comes with a plethora of features like routing, middleware, and built-in support for common tasks like JSON handling.
The Code
Below is a step-by-step walkthrough of a simple web server implemented in Rust using Actix-web.
Step 1: Setting Up the Project
First, create a new Rust project using Cargo:
cargo new rust_actix_web_server
cd rust_actix_web_server
Add actix-web and serde to your Cargo.toml:
[dependencies]
actix-web = "4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Step 2: Define the User Struct
We start by defining a simple User struct:
use serde::Serialize;
#[derive(Serialize)]
struct User {
user_id: u32,
name: &'static str,
}
static USERS: [User; 2] = [
User { user_id: 0, name: "John Doe" },
User { user_id: 1, name: "Jane Doe" },
];
Here, we use serde for serializing our User struct into JSON. We also create a static array of User instances.
Step 3: Creating Route Handlers
Next, we define our route handlers. The hello_world handler responds to the root URL (/) with a simple “Hello world!” message:
use actix_web::{get, HttpResponse, Responder};
#[get("/")]
async fn hello_world() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
The get_user handler fetches a user by their user_id:
use actix_web::{web, get};
#[get("/users/{user_id}")]
async fn get_user(user_id: web::Path<u32>) -> impl Responder {
let user = USERS.iter().find(|user| user.user_id == *user_id);
match user {
Some(user) => {
let body = serde_json::to_string(user).unwrap();
HttpResponse::Ok()
.content_type("application/json")
.body(body)
},
None => HttpResponse::NotFound().body("User not found"),
}
}
Here, we extract the user_id from the URL, search for the user in our static array, and respond with the user’s data in JSON format if found, or a “User not found” message otherwise.
Step 4: Configuring the Server
Finally, we configure our server in the main function:
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(hello_world)
.service(get_user)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
In the main function, we create an HttpServer, configure it with our route handlers using App::new, and bind it to 127.0.0.1:8080.
Running the Server
To run the server, use the following command:
cargo run
Open your browser and navigate to http://127.0.0.1:8080 to see the “Hello world!” message. For user data, navigate to http://127.0.0.1:8080/users/0 or http://127.0.0.1:8080/users/1.
Conclusion
In this blog, we’ve built a simple web server using Rust and Actix-web. We covered why Rust and Actix-web are excellent choices for web development and walked through the implementation of a basic server that serves static user data. This example demonstrates the powerful combination of Rust’s safety and performance with Actix-web’s high-speed, asynchronous capabilities. Whether you’re a seasoned Rustacean or new to the language, Actix-web offers a robust framework for building web applications.
カテゴリー: