Building a Basic REST API with Rust

administrator   19 May 2024



Introduction

Rust is known for its performance and safety, making it an excellent choice for building web applications. In this tutorial, we will walk through creating a basic REST API using Rust, utilizing the actix-web framework. By the end of this guide, you will have a simple API that can handle basic CRUD (Create, Read, Update, Delete) operations.

Prerequisites

Before we begin, ensure you have the following installed:
  • Rust (you can install it from rustup.rs)
  • Cargo (comes with Rust)

Setting Up the Project

First, let's create a new Rust project:
cargo new rust-rest-api

cd rust-rest-api
Open the Cargo.toml file and add the dependencies:
[dependencies]

actix-web = "4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
uuid = "1"

Creating the Main File

Let's start by creating a simple server. Open src/main.rs and modify it as follows:
use actix_web::{web, App, HttpServer, Responder, HttpResponse};

use serde::{Serialize, Deserialize};
use uuid::Uuid;

#[derive(Serialize, Deserialize)]
struct Item {
id: Uuid,
name: String,
}

async fn greet() -> impl Responder {
HttpResponse::Ok().body("Hello, world!")
}

#[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
}
Run the server with:
cargo run

Open your browser and navigate to http://127.0.0.1:8080. You should see "Hello, world!".

Adding CRUD Endpoints

Now, let's expand our API to handle CRUD operations for Item.

Create Item:

async fn create_item(item: web::Json<Item>) -> impl Responder {

HttpResponse::Created().json(item.into_inner())
}

Read Item:

async fn get_item(id: web::Path<Uuid>) -> impl Responder {

HttpResponse::Ok().json(Item {
id: *id,
name: String::from("Sample Item"),
})
}

Update Item:

async fn update_item(id: web::Path<Uuid>, item: web::Json<Item>) -> impl Responder {

HttpResponse::Ok().json(Item {
id: *id,
name: item.name.clone(),
})
}

Delete Item:

async fn delete_item(id: web::Path<Uuid>) -> impl Responder {

HttpResponse::NoContent().finish()
}

Update your main function to include these routes:
#[actix_web::main]

async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(greet))
.route("/item", web::post().to(create_item))
.route("/item/{id}", web::get().to(get_item))
.route("/item/{id}", web::put().to(update_item))
.route("/item/{id}", web::delete().to(delete_item))
})
.bind("127.0.0.1:8080")?
.run()
.await
}

Testing the API

You can test the API using curl or a tool like Postman.

Create Item:

curl -X POST http://127.0.0.1:8080/item -H "Content-Type: application/json" -d '{"id": "550e8400-e29b-41d4-a716-446655440000", "name": "NewItem"}'


Get Item:

curl http://127.0.0.1:8080/item/550e8400-e29b-41d4-a716-446655440000


Update Item:

curl -X PUT http://127.0.0.1:8080/item/550e8400-e29b-41d4-a716-446655440000 -H "Content-Type: application/json" -d '{"name": "UpdatedItem"}'


Delete Item:

curl -X DELETE http://127.0.0.1:8080/item/550e8400-e29b-41d4-a716-446655440000


Conclusion

Congratulations! You've created a basic REST API using Rust and actix-web. This tutorial covered setting up a Rust project, creating a simple server, and implementing basic CRUD operations. From here, you can expand the API with more features and robust error handling.