Introduction
In this tutorial, you will learn how to build a web server with Rust and the Actix-web framework on a DigitalOcean Droplet. You will set up a core server and create routes to manage a simple list of Todo items that supports common RESTful operations such as retrieving and creating Todos.
Prerequisites
Before you begin, make sure you have the following:
- One DigitalOcean Cloud Account To rotate a Droplet.
- An Ubuntu Droplet is up and running.
- Rust is installed on the Droplet.
- Familiarity with Rust principles including variables, functions, and attributes.
Step 1 – Setting Up Ubuntu Droplet
SSH into your DigitalOcean Droplet: Open your terminal and use the following command to SSH into your Droplet. Replace your_username with your actual username and your_droplet_ip with your Droplet IP address:
ssh your_username@your_droplet_ip
Update Package List: After logging in, update the package list to ensure you have the latest information on available packages:
sudo apt update
Install Rust: To install Rust, use the following command, which will download and run the Rust installation script:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Follow the on-screen instructions to complete the installation. After installation, you may need to restart your terminal or run:
source $HOME/.cargo/env
Install essential libraries: Install the libraries required to build Rust applications. You can install build-essential and libssl-dev using:
sudo apt install build-essential libssl-dev
Verify Rust installation: To verify that Rust is installed correctly, check the version:
rustc --version
Install Cargo (Rust Package Manager): Cargo is automatically installed with Rust. You can verify its installation by checking the version:
cargo --version
Step 2 – Launch the project
Let's create a new rust project sammy_todos using the payload
cargo new sammy_todos
Then find the Cargo.toml file. Go to the root directory of your Rust project. The Cargo.toml file is located in the same directory where you created your project (for example, sammy_todos). You can use the following command to change to your project directory:
cd sammy_todos/ lsBelow are the Rust project files that are automatically generated:
Output Cargo.toml srcAdd actix-web and serde as dependencies in Cargo.toml. Here, serde is required for Serialization and Deserialization.
vi Cargo.toml
And add the following lines under dependencies.
[dependencies] actix-web = "4.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0""Now use the following command to download and compile the dependencies:
cargo build
Step 3 – Create a Basic Server
In main.rs, add the following lines of code to start a main server. You need to go to the src directory inside your project.
use actix_web::{get, App, HttpServer, HttpResponse, Responder, web}; #[get("/")] async fn index() -> impl Responder { HttpResponse::Ok().body("Welcome to the Sammy Todo API!") } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(index) }) .bind("127.0.0.1:8080")? .run() .await }Run the server:
cargo run
To test the server, open a new terminal session and run the following command:
curl http://127.0.0.1:8080
You should receive the following response:
Output Welcome to the Sammy Todo API!Step 4 – Add a Todo Model
The Todo model is required to serialize the request and response. Add the following lines of code to the main.rs file.
use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize)] struct Todo { id: i32, title: String, completed: bool, }Step 5 – Implement Create todo
This API creates the todo, and it's a dummy API that just returns your todo, but you can implement it with databases to make it persistent.
#[get("/todos")] async fn create_todo(todo: web::Json ) -> impl Responder { HttpResponse::Ok().body(serde_json::to_string(&todo).unwrap()) }
Step 6 – Run Get todo
This API returns the todo with the id:
#[get("/todos/{id}")] async fn get_todo(id: web::Path ) -> impl Responder { let todo = Todo { id: id.into_inner(), title: "Learn Actix-Web".to_string(), completed: false, }; HttpResponse::Ok().body(serde_json::to_string(&todo).unwrap()) }Connect the service with your server
The rust server main.rs looks like this:
use actix_web::{get, App, HttpServer, HttpResponse, Responder, web}; #[get("/")] async fn index() -> impl Responder { HttpResponse::Ok().body("Welcome to the Sammy Todo API!") } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(index) .service(get_todo) .service(create_todo) }) .bind("127.0.0.1:8080")? .run() .await } use serde::{Serialize, Deserialize}; // Added Deserialize to imports #[derive(Serialize, Deserialize)] // Ensure Deserialize is imported struct Todo { id: i32, title: String, completed: bool, } #[get("/todos")] async fn create_todo(todo: web::Json ) -> impl Responder { HttpResponse::Ok().body(serde_json::to_string(&todo).unwrap()) } #[get("/todos/{id}")] async fn get_todo(id: web::Path ) -> impl Responder { let todo = Todo { id: id.into_inner(), title: "Learn Actix-Web".to_string(), completed: false, }; HttpResponse::Ok().body(serde_json::to_string(&todo).unwrap()) }Now, you can test it by sending a POST request with curl:
curl -X POST -H "Content-Type: application/json" -d '{"title": "Buy groceries"}' http://127.0.0.1:8080/todos
Result
Congratulations! You have successfully set up a basic web server using Rust and Actix. This tutorial will teach you how to create endpoints for retrieving and creating Todo items, providing a solid foundation for building more complex applications. To further enhance your application, integrate a database solution for data persistence, which will allow you to efficiently store and manage your Todo items.









