Building a REST API for Math Operations (+, *, /) with Rust, Actix, and Rhai🦀
Tags: rust, tauri
Published: 2024-03-22 16:45:05

---
title: Building a REST API for Math Operations  (+, *, /) with Rust, Actix, and Rhai🦀
published: true
date: 2024-03-22 09:03:32 UTC
tags: Rust, Tauri
canonical_url: https://eleftheriabatsou.hashnode.dev/building-a-rest-api-for-math-operations-with-rust-actix-and-rhai
---

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmvr4hlivqnbfz9vth36.jpeg)

### Introduction

Hello, Rust enthusiasts and friends! 🦀

Are you ready to embark on another journey in Rust? Today, we'll explore how to create a REST API that performs basic mathematical operations: addition, multiplication, and division. We'll use [Actix](https://actix.rs/), a powerful web framework for Rust, together with [Rhai](https://rhai.rs/), a lightweight scripting language, to achieve our goal.

This tutorial is designed with junior Rust developers in mind (as I'm also new to Rust), so we'll take it step by step, making sure everything is clear and easy to follow. Let's dive in and start coding!

{% embed https://twitter.com/BatsouElef/status/1765407725393957065 %}

_Feel free to show your support on_ [_X_](https://twitter.com/BatsouElef)_! 💙_

## **Setting Up Your Project**

First things first, you'll need to set up a new Rust project and we need to add our dependencies to the `Cargo.toml` file.

```
[dependencies]
actix-web = "4.0.1"
rhai = "1.6.1"

```

This will include Actix-web for handling HTTP requests and Rhai for scripting our mathematical operations.

_Note: You can find the complete project on_ [_GitHub_](https://github.com/EleftheriaBatsou/mathematical-operations-with-http-rhai-actix-rust)_._

## **Creating the Route Handlers**

Open the `main.rs` file in your project's `src` directory and let's start coding!

As mentioned in the above section, we'll need to import the necessary modules and traits from Actix and Rhai libraries to handle HTTP requests and execute Rhai scripts.

```
use actix_web::{HttpServer, get, App, web::Path, Responder};
use rhai::Engine;

```

**Route Handlers** : We'll define the 3 route handlers (`divide`, `multiply`, `add`) and use Actix macros. These handlers extract two integer parameters (`num1` and `num2`) from the URL path using the Path extractor.

```
#[get("/divide/{num1}/{num2}")]
#[get("/multiply/{num1}/{num2}")]
#[get("/add/{num1}/{num2}")]

```

The code for `divide`, `multiply`, `add` is pretty similar, so let me explain to you how we can build the `divide` function and you can build accordingly the other too (or check my [_GitHub_](https://github.com/EleftheriaBatsou/mathematical-operations-with-http-rhai-actix-rust) if you need more guidance).

```
#[get("/divide/{num1}/{num2}")]
async fn divide(path: Path<(i64, i64)>) -> impl Responder {
    let (num1, num2) = path.into_inner();

    let mut engine = Engine::new();
    engine.register_fn("num1", move || num1);
    engine.register_fn("num2", move || num2);

    let result = engine.eval_file::<i64>("src/divide.rhai".into()).unwrap();

    format!("{result}")
}

```

1. **Define an asynchronous route handler for division** : The function `divide` is marked with the `#[get("/divide/{num1}/{num2}")]` attribute, which tells Actix to call this function when an HTTP GET request is made to the `/divide/{num1}/{num2}` path. The `{num1}` and `{num2}` in the path are placeholders for the two numbers that will be divided.

2. **Extract path parameters** : The `path: Path<(i64, i64)>` argument uses Actix's `Path` extractor to automatically extract and parse the `num1` and `num2` path parameters into a tuple of two `i64` numbers.

3. **Initialize Rhai Engine** : A new `Engine` instance from the Rhai scripting language is created. This engine will be used to evaluate Rhai scripts.

4. **Register functions in Rhai Engine** : The `engine.register_fn("num1", move || num1);` and `engine.register_fn("num2", move || num2);` lines register two functions, `num1` and `num2`, in the Rhai engine. These functions, when called from Rhai scripts, will return the values of `num1` and `num2` that were extracted from the path.

5. **Evaluate Rhai script** : The `engine.eval_file::<i64>("src/divide.rhai".into()).unwrap();` line tells the Rhai engine to evaluate (execute) the script located in `src/divide.rhai` (we'll write this a little bit later). This script performs the division operation using the `num1` and `num2` values. The result of the script evaluation is expected to be an `i64` integer, which is the result of the division.

6. **Return the result** : Finally, the result of the division is formatted as a string and returned as the HTTP response.

(Similarly, write the code for `multiply` and `add.`)

## **Creating the REST API**

1. **Start Actix web server** : The `#[actix_web::main]` attribute marks the `main` function as the entry point of the web server application. It allows the function to be `async`, making it possible to use asynchronous programming within.

2. **Create a new HTTP server instance** : `HttpServer::new()` is called to create a new instance of an HTTP server.

3. **Configure the application** : Inside the closure passed to `HttpServer::new()`, `App::new()` is called to create a new application instance. This application is configured with services (endpoints) that it should provide.

4. **Register services** : The `.service()` method is used to add services to the application. Here, `multiply`, `add`, and `divide` are the names of the functions that handle requests to their respective endpoints.

5. **Bind to an address** : `.bind(("127.0.0.1", 8080))?` tells the HTTP server to listen for incoming connections on the local address `127.0.0.1` ([localhost](http://localhost)) and port `8080`. The `?` operator is used for error handling; if binding fails (for example, if the port is already in use), the application will return an error and exit.

6. **Run the server** : `.run().await` starts the HTTP server and awaits its completion. The server runs indefinitely, handling incoming requests according to the services defined, until it's manually stopped or an unrecoverable error occurs.

Here's how the final part looks like:

```
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(multiply)
            .service(add)
            .service(divide)
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

```

## **Rhai Script for Operations**

Inside the `src` directory, create three Rhai script files: `add.rhai`, `multiply.rhai`, and `divide.rhai`.

Here's what the `multiply.rhai` looks like:

```
fn multiply(num1, num2) {
    return num1 * num2;
}

let num1 = num1();
let num2 = num2();

multiply(num1, num2);

```

1. **Define a** `multiply` **function** : A function named `multiply` is defined with two parameters `num1` and `num2`. This function performs multiplication of `num1` and `num2` and returns the result.

2. **Invoke registered functions** : The lines `let num1 = num1();` and `let num2 = num2();` invoke functions named `num1` and `num2` that have been previously registered in the Rhai engine. These functions return the values of `num1` and `num2` that were extracted from the request path and passed to the script.

3. **Call the** `multiply` **function** : Finally, the `multiply` function is called with the values of `num1` and `num2` as arguments. The result of this operation is the product of `num1` and `num2`, which is the intended outcome of the script.

The `add.rhai` and `divide.rhai` scripts are similar, just replace `multiply` with the respective operation.

## **Running the Program and Practical Tips**

With everything set up, it's time to run our API. Open your terminal and execute:

```
cargo run

```

After the project compiles and starts, open your browser and try accessing something like [`http://localhost:8080/{operation}/{num1}/`](http://localhost:8080/multiply/5/3)`{num2}`.

**Practical Tips:**

- For example, with [`http://localhost:8080/multiply/5/3`](http://localhost:8080/multiply/5/3)you should see the result of the multiplication operation, or with [`http://localhost:8080/add/8/`](http://localhost:8080/multiply/5/3)`4` the result of the adding operation.

- Use ctrl + c (on Windows) to stop the program

- To kill a port you can use something like: sudo kill -9 `sudo lsof -t -i:8080`

## **Conclusion**

Congratulations! 🎊 You've just created a REST API in Rust using Actix and Rhai for performing basic mathematical operations. This project showcases the power and flexibility of Rust for web development, as well as the ease of integrating scripting capabilities with Rhai. Happy coding!

* * *

👋 Hello, I'm Eleftheria, **Community Manager,** developer, public speaker, and content creator.

🥰 If you liked this article, consider sharing it.

🔗 [**All links**](https://limey.io/batsouelef) | [**X**](https://twitter.com/BatsouElef) | [**LinkedIn**](https://www.linkedin.com/in/eleftheriabatsou/)