...
Salvo

Building a REST API with Rust and Salvo Framework

PostgreSQL Integration

This guide will walk you through creating a REST API using Rust and the Salvo framework, connecting to a PostgreSQL database. The API will have two endpoints:

  • GET /api/getUserData: Retrieves user data from the users table based on the provided user_id parameter.
  • POST /api/updateUser: Updates user data in the users table based on the provided user_id, fullname, and email parameters.

Prerequisites:

  • Rust installed
  • Basic understanding of Rust programming
  • Familiarity with REST API concepts
  • PostgreSQL database set up

Steps:

  1. Create a Rust project:
   cargo new salvo_api
  1. Install Salvo and dependencies:
   cargo add salvo salvo_postgres --version ^0.2.0
  1. Define data models: Create a models.rs file to define the data structures for users:
   use salvo::serde::{Deserialize, Serialize};

   #[derive(Debug, Deserialize, Serialize)]
   pub struct User {
       user_id: i32,
       fullname: String,
       email: String,
   }
  1. Implement database access (using Salvo’s salvo_postgres extension):
   // Add `sqlx` and `postgres` dependencies to `Cargo.toml`
   cargo add sqlx postgres

   // Create a `db.rs` file for database operations
   use salvo::{
       Body, Request, Response, State,
       BodyExt,
       Router,
       Salvo,
       salvo_postgres::Pool,
   };
   use crate::models::User;

   pub async fn get_user_data(pool: &Pool, user_id: i32) -> Result<User, salvo::Error> {
       let row = sqlx::query_as!(User, "SELECT * FROM users WHERE user_id = $1", user_id)
           .fetch_optional(pool)
           .await
           .unwrap();

       match row {
           Some(user) => Ok(user),
           None => Err(salvo::Error::NotFound),
       }
   }

   pub async fn update_user(pool: &Pool, user: User) -> Result<(), salvo::Error> {
       sqlx::query!("UPDATE users SET fullname = $1, email = $2 WHERE user_id = $3", user.fullname, user.email, user.user_id)
           .execute(pool)
           .await
           .unwrap();

       Ok(())
   }
  1. Create route handlers: Create a routes.rs file to define the API routes and handlers:
   use salvo::{
       Body, Request, Response, State,
       BodyExt,
       Router,
       Salvo,
       salvo_postgres::Pool,
   };
   use crate::{db::*, models::User};

   pub async fn get_user_data_handler(req: Request<State<Pool>>, user_id: i32) -> Response {
       let user = get_user_data(&req.state(), user_id).await.unwrap_or_else(|_| User { user_id: 0, fullname: "".to_string(), email: "".to_string() });
       Body::json(user).to_response()
   }

   pub async fn update_user_handler(req: Request<State<Pool>>, mut user: User) -> Response {
       let user_id = user.user_id;
       update_user(&req.state(), &user).await.unwrap();
       Body::json(user).to_response()
   }
  1. Register routes and start the server: Create a main.rs file to register routes and start the server: “`rust
    use salvo::{
    Body, Request, Response, State,
    BodyExt,
    Router,
    Salvo,
    salvo_postgres::Pool,
    };
    use crate::routes::*; pub async fn run_server() {
    let pool = Pool::connect(“postgres://user:password@localhost:5432/db”)
    .await
    .unwrap(); let router = Router::new()
    .get(“/api/getUserData/{user_id}”, get_user_data

MySQL Integration

This guide will walk you through creating a REST API using Rust and the Salvo framework, connecting to a MySQL database. The API will have two endpoints:

  • GET /api/getUserData: Retrieves user data from the users table based on the provided user_id parameter.
  • POST /api/updateUser: Updates user data in the users table based on the provided user_id, fullname, and email parameters.

Prerequisites:

  • Rust installed
  • Basic understanding of Rust programming
  • Familiarity with REST API concepts
  • MySQL database set up

Steps:

  1. Create a Rust project:
cargo new salvo_api
  1. Install Salvo and dependencies:
cargo add salvo salvo_mysql --version ^0.2.0
  1. Define data models:

Create a models.rs file to define the data structures for users:

use salvo::serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
pub struct User {
    user_id: i32,
    fullname: String,
    email: String,
}
  1. Implement database access (using Salvo’s salvo_mysql extension):
// Add `mysql` dependency to `Cargo.toml`
cargo add mysql

// Create a `db.rs` file for database operations
use salvo::{
    Body, Request, Response, State,
    BodyExt,
    Router,
    Salvo,
    salvo_mysql::Pool,
};
use crate::models::User;

pub async fn get_user_data(pool: &Pool, user_id: i32) -> Result<User, salvo::Error> {
    let mut conn = pool.get_conn().await.unwrap();
    let row = conn.query_row::<_, User>("SELECT * FROM users WHERE user_id = ?", user_id).await.unwrap();
    Some(row)
}

pub async fn update_user(pool: &Pool, user: User) -> Result<(), salvo::Error> {
    let mut conn = pool.get_conn().await.unwrap();
    conn.execute("UPDATE users SET fullname = ?, email = ? WHERE user_id = ?", user.fullname, user.email, user.user_id).await.unwrap();
    Ok(())
}
  1. Create route handlers:

Create a routes.rs file to define the API routes and handlers:

use salvo::{
    Body, Request, Response, State,
    BodyExt,
    Router,
    Salvo,
    salvo_mysql::Pool,
};
use crate::{db::*, models::User};

pub async fn get_user_data_handler(req: Request<State<Pool>>, user_id: i32) -> Response {
    let user = get_user_data(&req.state(), user_id).await.unwrap_or_else(|_| User { user_id: 0, fullname: "".to_string(), email: "".to_string() });
    Body::json(user).to_response()
}

pub async fn update_user_handler(req: Request<State<Pool>>, mut user: User) -> Response {
    let user_id = user.user_id;
    update_user(&req.state(), &user).await.unwrap();
    Body::json(user).to_response()
}
  1. Register routes and start the server:

Create a main.rs file to register routes and start the server:

use salvo::{
    Body, Request, Response, State,
    BodyExt,
    Router,
    Salvo,
    salvo_mysql::Pool,
};
use crate::routes::*;

pub async fn run_server() {
    let pool = Pool::connect("mysql://user:password@localhost:3306/db")
        .await
        .unwrap();

    let router = Router::new()
        .get("/api/getUserData/{user_id}", get_user_data_handler)
        .post("/api/updateUser", update_user_handler);

    let salvo = Salvo::new(router);
    salvo.run("0.0.0.0:8080").await.unwrap();
}

Run the API:

cargo run

The API will be

Leave a Reply

Your email address will not be published. Required fields are marked *