REST API Development with Rust
This article is an extension of article Application Development with Rust. The purpose of this article is to demonstrate development of API using Rust. This article will provide an example design and implementation of REST API to expose functionality already developed. The hope is that the reader will be able to explore the example implementation and extend this to further solidify their understanding of developing API using Rust.
I developed this code as part of my learning Rust. I had already developed code in Rust for memory allocation functionality. I wanted to expose that functionality as REST APIs and wanted to develop it in Rust. With my research, I was able to build a REST API. In this article, I would want to share the use-cases, and the design that I based this code on. My hope is that this will help the reader not to worry about the use-case or design, rather the reader will explore the implementation using Rust, and this may expedite the Rust learning for the reader.
The use-case section of this article links to the repo with existing memory and virtual memory allocation functionality developed in Rust. The design section details the steps required to build REST API to expose existing functionality. The run and extend section details the process to run this code, and options to extend this code. I hope that this makes it easier for the reader to learn Rust.
The existing application has two modules. The module Memory has different algorithms for allocating memory for a requesting process. Here are the list of functions implemented in this module.
Similarly, the module Virtual has implementation for a number of algorithms for allocating virtual memory. This article will provide an example implementation of a REST API that is exposing best_fit_allocate functionality. The hope is that the reader will follow the example and expose other functionalities through REST APIs.
I used actix framework for developing APIs in Rust.
This web application is configured to run on localhost (127.0.0.1) and port 8080. This configuration has been implemented in src/main.rs. Few other things that have been configure in src/main.rs.
- Tag actix_web::main is exposing this application as a web application.
- HttpServer is instantiating the embedded web server to service web requests.
- There are two service function calls to configure two different paths
1. localhost:8080 : This serves the contents common across all modules. I’m calling it home and it’s currently responding text “OS Services …”.2. localhost:8080/os/memory/ : This serves the contents from Memory module.
The intent for this design is to provide different contexts for different resources as per REST best practices. The hope is that the reader will extend this repo and add a new path localhost:8080/os/virtual/ to serve contents from Virtual module.
- The path localhost:8080/os/memory/ requires a path parameter “alloc_method”. The current implementation doesn’t require any specific value for alloc_method, it can be anything. The hope is that the reader will modify this code to call different functions based on allocation method requested. The reader may want to explore Rust enum structure and pattern matching feature “match” to implement this.
The “src” folder contains code for creating different API endpoints and “tests” folder contains code to test those respective endpoints.
The folder “src” has a subfolder “services” that contains code for different contexts such as home, memory, and virtual.
To achieve this structure in Rust,
1. module services is defined in lib.rs2. different contexts are defined as modules in services.rs. As of this writing, the modules defined are home, memory, and virtual.After this step, the subfolder services is created and Rust code is written for different modules in files home.rs, memory.rs, and virtual.rs.
As of this writing, the code is there only in memory.rs to expose best_fit_allocate functionality as a REST API.
- The API is expecting a JSON payload as input. Here is an example payload
}To achieve this in Rust,1. Two structs have been defined: MemoryMap, and MemoryAllocationRequest2. I used Serde framework for serializing and deserializing these data structures. The use of derive macro from Serde generates implementations of the Serialize and Deserialize traits for these data structure.3. The Json helper from module web in crate actix-web is used to extract MemoryAllocationRequest struct structure from input Json payload.
- The API calls function best_fit_allocate defined in module memory::memory of crate mos_rust to allocate memory.
To achieve this in Rust,1. I’ve defined a dependency on mos_rust, and I’ve the project mos_rust at path ../mos_rust with respect to this project
- The API response is in Json format.
To achieve this, I used the method “json” of “HttpResponseBuilder”. The “Ok” method of HttpResponse returns “HttpResponseBuilder”. This helped to create the response in Json format.
With the above explanation, the hope is that the reader can follow this example and expose other functions as REST APIs.
Run and Extend
There are two options to run and test the existing code.
- Clone or download this code. Then go to the code directory, and run the command “cargo test”. Upon successful run, you will see message like
Running tests/test_memory.rs running 2 test
test tests::test_index_get ... ok
test tests::test_best_fit_allocate_get ... ok".
- Use a tool like Postman to test your API. Clone or download this code. Then go to the code directory, and run the command “cargo run”. You will see message like
Finished dev [unoptimized + debuginfo] target(s) in 0.26s
Now use Postman to send a POST request to localhost:8080/os/memory/best_fit. Here is an example request and response body for the request
Some ideas have been discussed already in this article for extending this repo. I hope the reader can expose other functions implemented in the modules Memory and Virtual as REST APIs.
This is an attempt to provide an example design and implementation of REST API using Rust to help the reader to learn Rust. The reader is expected to explore the code on their own. This will be revised based on feedback from readers to achieve the goal of making it easier to learn Rust.
If the reader wishes, they can build a UI using Rust WebAssembly. This will serve as a frontend to APIs.
Originally published at https://github.com.