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, a powerful web framework for Rust, together with Rhai, 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!
Feel free to show your support on X! ๐
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.
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 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}")
}
Define an asynchronous route handler for division : The function
divideis 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.Extract path parameters : The
path: Path<(i64, i64)>argument uses Actix'sPathextractor to automatically extract and parse thenum1andnum2path parameters into a tuple of twoi64numbers.Initialize Rhai Engine : A new
Engineinstance from the Rhai scripting language is created. This engine will be used to evaluate Rhai scripts.Register functions in Rhai Engine : The
engine.register_fn("num1", move || num1);andengine.register_fn("num2", move || num2);lines register two functions,num1andnum2, in the Rhai engine. These functions, when called from Rhai scripts, will return the values ofnum1andnum2that were extracted from the path.Evaluate Rhai script : The
engine.eval_file::<i64>("src/divide.rhai".into()).unwrap();line tells the Rhai engine to evaluate (execute) the script located insrc/divide.rhai(we'll write this a little bit later). This script performs the division operation using thenum1andnum2values. The result of the script evaluation is expected to be ani64integer, which is the result of the division.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
Start Actix web server : The
#[actix_web::main]attribute marks themainfunction as the entry point of the web server application. It allows the function to beasync, making it possible to use asynchronous programming within.Create a new HTTP server instance :
HttpServer::new()is called to create a new instance of an HTTP server.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.Register services : The
.service()method is used to add services to the application. Here,multiply,add, anddivideare the names of the functions that handle requests to their respective endpoints.Bind to an address :
.bind(("127.0.0.1", 8080))?tells the HTTP server to listen for incoming connections on the local address127.0.0.1(localhost) and port8080. 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.Run the server :
.run().awaitstarts 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);
Define a
multiplyfunction : A function namedmultiplyis defined with two parametersnum1andnum2. This function performs multiplication ofnum1andnum2and returns the result.Invoke registered functions : The lines
let num1 = num1();andlet num2 = num2();invoke functions namednum1andnum2that have been previously registered in the Rhai engine. These functions return the values ofnum1andnum2that were extracted from the request path and passed to the script.Call the
multiplyfunction : Finally, themultiplyfunction is called with the values ofnum1andnum2as arguments. The result of this operation is the product ofnum1andnum2, 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}/{num2}.
Practical Tips:
For example, with
http://localhost:8080/multiply/5/3you should see the result of the multiplication operation, or withhttp://localhost:8080/add/8/4the 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.

Top comments (0)