Tutorial

How to Set Up a Web Server with Rust and Actix

Published on January 3, 2025
How to Set Up a Web Server with Rust and Actix

Introduction

In this tutorial, you’ll learn how to build a web server with Rust and the Actix-web framework on a DigitalOcean Droplet. You’ll set up a basic server and create routes to manage a simple list of Todo items, supporting common RESTful operations like retrieving and creating Todos.

Prerequisites

Before you begin, ensure you have the following:

Step 1 - Setting up the Ubuntu Droplet

  1. 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 the IP address of your Droplet:

    ssh your_username@your_droplet_ip
    
  2. Update the package list: Once logged in, update the package list to ensure you have the latest information on available packages:

    sudo apt update
    
  3. Install Rust: To install Rust, use the following command, which downloads and runs 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
    
  4. Install necessary libraries: Install the required libraries for building Rust applications. You can install build-essential and libssl-dev using:

    sudo apt install build-essential libssl-dev
    
  5. Verify Rust installation: To confirm that Rust has been installed correctly, check the version:

    rustc --version
    
  6. Install Cargo (Rust package manager): Cargo is installed automatically with Rust. You can verify its installation by checking the version:

    cargo --version
    

Step 2 - Setting Up the Project

Let’s create a new rust project sammy_todos using cargo

cargo new sammy_todos

Next, find the Cargo.toml file. Navigate to the root directory of your Rust project. The Cargo.toml file is located in the same directory where you created your project (e.g., sammy_todos). You can use the following command to change to your project directory:

cd sammy_todos/
ls

Below are the Rust project files files which are automatically generated:

Output
Cargo.toml src

Add actix-web and serde as dependencies in Cargo.toml. Here, serde is needed for Serialization and Deserialization.

vi Cargo.toml

And add the following lines under the dependencies.

[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Now to download and compile dependencies use the below command:

cargo build

Step 3 - Creating a Basic Server

In main.rs, add the following lines of code to set up a basic server. You must navigate to the src directory inside your Project.

main.rs
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 get the following response:

Output
Welcome to the Sammy Todo API!

Step 4 - Adding a Todo Model

Todo model is needed to serialize and deserialize the request and response. Add the following lines of code inside the main.rs file.

main.rs
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Todo {
    id: i32,
    title: String,
    completed: bool,
}

Step 5 - Implement Create todo

This API creates todo, and this is a dummy API that returns your todo only, but you can implement it with databases to make it persistent

main.rs
#[get("/todos")]
async fn create_todo(todo: web::Json<Todo>) -> impl Responder {
    HttpResponse::Ok().body(serde_json::to_string(&todo).unwrap())
}

Step 6 - Implement Get todo

This API returns todo by id:

main.rs
#[get("/todos/{id}")]
async fn get_todo(id: web::Path<i32>) -> 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())
}

Bind the services with our server

This is how the rust server main.rs would look like:

main.rs
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<Todo>) -> impl Responder {
    HttpResponse::Ok().body(serde_json::to_string(&todo).unwrap())
}

#[get("/todos/{id}")]
async fn get_todo(id: web::Path<i32>) -> 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

Conclusion

Congratulations! You have successfully set up a basic web server using Rust and Actix. This tutorial taught you to create endpoints to retrieve and create Todo items, providing a solid foundation for building more complex applications. To enhance your app further, consider integrating a database solution for data persistence, allowing you to store and manage your Todo items effectively. Keep exploring, and happy coding!

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar

Senior Engineer I


Default avatar

Sr Technical Writer

Senior Technical Writer @ DigitalOcean | 2x Medium Top Writers | 2 Million+ monthly views & 34K Subscribers | Ex Cloud Consultant @ AMEX | Ex SRE(DevOps) @ NUTANIX


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.