-
-
Save indiranell/de278fccde27f095ee7563afbf24690e to your computer and use it in GitHub Desktop.
Rust code for Reqwest crate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Rust script using reqwests to make Get and Post call to cars api to get and add cars | |
use std::fs; | |
use serde_derive::{Deserialize, Serialize}; | |
use std::time::Duration; | |
use serde_json::Value as JsonValue; | |
#[derive(Debug, Deserialize)] | |
struct ApiConfig { | |
username: String, | |
password: String, | |
} | |
#[derive(Debug, Deserialize)] | |
struct Config { | |
api: ApiConfig, | |
} | |
#[derive(Debug, Deserialize, Serialize)] | |
struct Car { | |
brand: String, | |
car_type: String, | |
name: String, | |
price_range: String, | |
} | |
#[derive(Debug, Deserialize, Serialize)] | |
struct CarsResponse { | |
cars_list: Vec<Car>, | |
successful: bool, | |
} | |
#[tokio::main] | |
async fn main() { | |
let config_str = fs::read_to_string("config.toml").expect("Failed to read config file"); | |
// convert string into a Config struct | |
let config: Config = toml::from_str(&config_str).expect("Failed to parse config"); | |
// Read the username and password | |
let username = &config.api.username; | |
let password = &config.api.password; | |
match get_cars(username, password).await { | |
Ok(json_response) => { | |
if validate_get_response(&json_response) { | |
println!("Cars response is valid."); | |
println!("Cars: {:#?}", json_response); | |
} else { | |
println!("Invalid cars response structure."); | |
} | |
} | |
Err(err) => println!("Error: {}", err), | |
} | |
let json_data = r#" | |
{ | |
"name": "Figo", | |
"brand": "Ford", | |
"price_range": "5-6lacs", | |
"car_type": "hatchback" | |
} | |
"#; | |
match add_cars(username, password, json_data).await { | |
Ok(response) => { | |
if validate_add_response(&response) { | |
println!("Car addition successful."); | |
println!("Response: {:#?}", response); | |
} else { | |
println!("Invalid car addition response structure."); | |
} | |
} | |
Err(err) => println!("Error: {}", err), | |
} | |
} | |
fn validate_get_response(cars_response: &JsonValue) -> bool { | |
// Validate that the JSON response has the expected structure | |
if let Ok(parsed_response) = serde_json::from_value::<CarsResponse>(cars_response.clone()) { | |
// Check if each Car object in cars_list has all required fields | |
for car in &parsed_response.cars_list { | |
if car.brand.is_empty() || car.car_type.is_empty() || car.name.is_empty() || car.price_range.is_empty() { | |
return false; | |
} | |
} | |
true | |
} else { | |
false | |
} | |
} | |
fn validate_add_response(response: &serde_json::Value) -> bool { | |
// Check if the response contains the successful response | |
if let Some(successful) = response.get("successful") { | |
if let Some(successful_bool) = successful.as_bool() { | |
return successful_bool; | |
} | |
} | |
false // If the expected field or type is missing, consider the response as invalid | |
} | |
async fn get_cars(username: &str, password: &str) -> Result<serde_json::Value, Box<dyn std::error::Error>> { | |
// Read the content of the "config.toml" file into a string | |
let client = reqwest::Client::new(); | |
let response = match client.get("http://localhost:5000/cars") | |
.basic_auth(username, Some(password)) | |
.timeout(Duration::from_secs(10)) | |
.send() | |
.await { | |
Ok(res) => { | |
// Check for specific status codes | |
if res.status().is_client_error() { | |
Err(format!("Server returned a client error: {}", res.status()).into()) | |
} else if res.status().is_server_error() { | |
return Err(format!("Server returned a error, check your request data: {}", res.status()).into()); | |
} | |
else { | |
Ok(res) | |
} | |
} | |
Err(err) => { | |
// Handle specific error types | |
if err.is_connect() { | |
return Err("Failed to connect to the server. Please make sure the server is running.".into()); | |
} | |
else if err.is_timeout() { | |
return Err(format!("Request timed out: {}", err).into()); | |
} else { | |
return Err(Box::new(err)); | |
} | |
} | |
}; | |
// Handle the response and extract JSON | |
let result_json: serde_json::Value = match response { | |
Ok(res) => match res.json().await { | |
Ok(json) => json, | |
Err(err) => return Err(Box::new(err)), | |
}, | |
Err(err) => return Err(err), | |
}; | |
Ok(result_json) | |
} | |
async fn add_cars(username: &str, password: &str, json_data: &str) -> Result<serde_json::Value, Box<dyn std::error::Error>> { | |
let client = reqwest::Client::new(); | |
let response = match client.post("http://localhost:5000/cars/add") | |
.basic_auth(username, Some(password)) | |
.timeout(Duration::from_secs(10)) | |
.header(reqwest::header::CONTENT_TYPE, "application/json") | |
.body(json_data.to_string()) | |
.send() | |
.await { | |
Ok(res) => { | |
// Check for specific status codes | |
if res.status().is_client_error() { | |
return Err(format!("Server returned a client error: {}", res.status()).into()); | |
} | |
else if res.status().is_server_error() { | |
return Err(format!("Server returned a error, check your request data: {}", res.status()).into()); | |
} else { | |
Ok(res) | |
} | |
} | |
Err(err) => { | |
// Handle specific error types | |
if err.is_connect() { | |
return Err("Failed to connect to the server. Please make sure the server is running.".into()); | |
} else if err.is_timeout() { | |
return Err(format!("Request timed out: {}", err).into()); | |
} | |
else { | |
return Err(Box::new(err)); | |
} | |
} | |
}; | |
// Handle the response and extract JSON | |
let result_json: serde_json::Value = match response { | |
Ok(res) => match res.json().await { | |
Ok(json) => json, | |
Err(err) => return Err(Box::new(err)), | |
}, | |
Err(err) => return Err(err), | |
}; | |
Ok(result_json) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment