Are you planning to develop an API-only backend using Rust and Actix-web? If so, you need to know how to return JSON responses from Actix-web. This post briefly shows how to create a Rust application using actix-web that returns JSON responses.
Rust Requirements For Actix-Web
These are things used in the post.
- Windows 10
- Rust 1.52.1
- IntelliJ IDEA
- Using Rust plugin
- Actix-web 3.3.2
- serde 1.0.126
Create a new Rust Actix-Web Project
Go to File -> New -> Project... and choose Rust. Then click Next and enter the Project Name and Project Location. Click Finish to complete.
Update Cargo.toml For Actix-Web
Next, modify the cargo.toml to include two dependencies – actix-web and serde. These are the only two dependencies we need for our sample Actix-web application.
1 2 3 4 5 6 7 8 9 | [package] name = "rust-actix-web-json-response" version = "0.1.0" authors = ["Karl San Gabriel <karl.sangabriel@gmail.com>"] edition = "2018" [dependencies] actix-web = "3.3.2" serde = { version = "1.0.126", features = ["derive"] } |
Create Rust Codes To Return JSON Response
To server JSON contents, we use web::Json() from actix-web. First, we use we import the struct and traits we need.
1 2 | use actix_web::{web, App, HttpServer, Responder}; use serde::Serialize; |
Then, we create the struct to represent a country. Our Rust Actix-web application returns a JSON response representing a struct country list.
1 2 3 4 5 | #[derive(Serialize)] struct Country { country_code: String, country_name: String } |
Then, we create an HTTP request handle for HTTP GET /countries. Note that the function is async.
1 2 3 4 5 6 7 8 9 | async fn get_country_list() -> impl Responder { let mut vec:Vec<Country> = Vec::new(); vec.push(Country{country_code: "PH".to_string(), country_name: "Philippines".to_string()}); vec.push(Country{country_code: "MY".to_string(), country_name: "Malaysia".to_string()}); vec.push(Country{country_code: "ID".to_string(), country_name: "Indonesia".to_string()}); return web::Json(vec); } |
Lastly, we implement the main() function. The codes in this function are straightforward.
1 2 3 4 5 6 7 8 9 10 | #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/countries", web::get().to(get_country_list)) }) .bind(("127.0.0.1", 8080))? .run() .await } |
The codes listen at port 8088 on localhost for HTTP GET requests to /countries.
Test Actix-Web And JSON Response
Finally, we can test our Rust codes that make Actix-web return a JSON response. For example, go to localhost:8088/countries using a browser, and the application returns a JSON response as follows. The response contains three JSON objects our Actix-web application took from the get_country_list function.
As we can see, we get a JSON response that contains an array of JSON representing countries. Also, the response header content-type indicates that the response is of type application/json.
BASIC and Bearer Authentications (Optional)
Suppose we want to secure our application, we could use Actix-web BASIC or Bearer authentication.