use rust_api_calling::{ApiClient, ApiError, RequestConfig};
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Serialize, Deserialize)]
struct User {
#[serde(rename = "_id", skip_serializing)]
id: Option<serde_json::Value>, name: Option<String>,
email: Option<String>,
password: Option<String>,
role: Option<String>,
number: Option<String>,
}
#[derive(Debug, Serialize)]
struct CreateUserRequest {
name: String,
email: String,
password: String,
role: String,
number: String,
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "info".into()),
)
.init();
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ rust_api_calling — CRUD API Usage Examples ║");
println!("║ Server: https://rust-crud-pay9.onrender.com ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
let client = ApiClient::builder()
.base_url("https://rust-crud-pay9.onrender.com")
.default_timeout(Duration::from_secs(60)) .default_header("Accept", "application/json")
.session_enabled(true) .build()
.expect("Failed to create ApiClient");
println!("✅ ApiClient created with base_url and session management\n");
println!("━━━ Example 1: GET / (Health Check) ━━━");
println!(" Waking up the server (Render free tier may take ~30s)...\n");
match client.get::<String>("/", None, None).await {
Ok(response) => {
println!(" ✅ Status: {}", response.status);
println!(" 📝 Response: {}", response.body);
}
Err(e) => println!(" ❌ Error: {}\n", e),
}
println!();
println!("━━━ Example 2: POST /add-user (Create User) ━━━");
let new_user = CreateUserRequest {
name: "Keval Thumar".to_string(),
email: "kevalthumar@gmail.com".to_string(),
password: "fsdfuphnsd921kjds".to_string(),
role: "developer".to_string(),
number: "9876543210".to_string(),
};
println!(" 📤 Sending: {:?}\n", new_user);
match client
.post::<serde_json::Value, _>("/add-user", Some(&new_user), None)
.await
{
Ok(response) => {
println!(" ✅ Status: {}", response.status);
println!(
" 📝 Response: {}",
serde_json::to_string_pretty(&response.body).unwrap()
);
}
Err(ApiError::HttpError { status, body }) => {
println!(" ⚠️ HTTP {}: {}", status, body);
}
Err(e) => println!(" ❌ Error: {}", e),
}
println!();
println!("━━━ Example 3: GET /get-all-users (List All) ━━━");
match client
.get::<serde_json::Value>("/get-all-users", None, None)
.await
{
Ok(response) => {
println!(" ✅ Status: {}", response.status);
if let Some(users) = response.body.as_array() {
println!(" 👥 Total users: {}", users.len());
for (i, user) in users.iter().take(3).enumerate() {
println!(
" [{}] name: {}, email: {}, role: {}",
i + 1,
user.get("name").and_then(|v| v.as_str()).unwrap_or("N/A"),
user.get("email").and_then(|v| v.as_str()).unwrap_or("N/A"),
user.get("role").and_then(|v| v.as_str()).unwrap_or("N/A"),
);
}
if users.len() > 3 {
println!(" ... and {} more", users.len() - 3);
}
} else {
println!(
" 📝 Response: {}",
serde_json::to_string_pretty(&response.body).unwrap()
);
}
}
Err(e) => println!(" ❌ Error: {}", e),
}
println!();
println!("━━━ Example 4: GET /get-all-users (Typed into Vec<User>) ━━━");
match client
.get::<Vec<User>>("/get-all-users", None, None)
.await
{
Ok(response) => {
println!(" ✅ Status: {}", response.status);
println!(" 👥 Deserialized {} users into Vec<User>", response.body.len());
for (i, user) in response.body.iter().take(3).enumerate() {
println!(
" [{}] {:?} — {} ({})",
i + 1,
user.name.as_deref().unwrap_or("N/A"),
user.email.as_deref().unwrap_or("N/A"),
user.role.as_deref().unwrap_or("N/A"),
);
}
}
Err(e) => println!(" ❌ Error: {}", e),
}
println!();
println!("━━━ Example 5: GET /get-user/{{id}} (Single User) ━━━");
println!(" First, fetching all users to get a valid ID...\n");
let first_user_id = client
.get::<serde_json::Value>("/get-all-users", None, None)
.await
.ok()
.and_then(|resp| {
resp.body
.as_array()?
.first()?
.get("_id")?
.get("$oid")
.and_then(|v| v.as_str().map(String::from))
});
if let Some(id) = first_user_id {
println!(" 🔍 Fetching user with ID: {}", id);
match client
.get::<serde_json::Value>(&format!("/get-user/{}", id), None, None)
.await
{
Ok(response) => {
println!(" ✅ Status: {}", response.status);
println!(
" 📝 User: {}",
serde_json::to_string_pretty(&response.body).unwrap()
);
}
Err(e) => println!(" ❌ Error: {}", e),
}
} else {
println!(" ⚠️ No users found — skipping single user fetch");
}
println!();
println!("━━━ Example 6: Error Handling (invalid user ID) ━━━");
match client
.get::<serde_json::Value>("/get-user/69c8cf69d80a457f574df9b2", None, None)
.await
{
Ok(response) => {
println!(" 📝 Status: {} — Response: {}", response.status, response.raw_body);
}
Err(ApiError::HttpError { status, body }) => {
println!(" ✅ Got expected HTTP error!");
println!(" ⚠️ Status: {}", status);
println!(" 📝 Body: {}", body);
}
Err(e) => {
println!(" ❌ Error: {}", e);
}
}
println!();
println!("━━━ Example 7: Custom RequestConfig (timeout + headers) ━━━");
let custom_config = RequestConfig::new()
.timeout(Duration::from_secs(10))
.header("X-Request-ID", "example-rust-12345")
.header("X-Client-Version", "1.0.0");
match client
.get::<serde_json::Value>("/get-all-users", None, Some(custom_config))
.await
{
Ok(response) => {
println!(" ✅ Status: {}", response.status);
println!(" 📋 Response headers received: {} total", response.headers.len());
if let Some(ct) = response.header("content-type") {
println!(" Content-Type: {}", ct);
}
}
Err(e) => println!(" ❌ Error: {}", e),
}
println!();
println!("━━━ Example 8: Absolute URL (external API, bypasses base_url) ━━━");
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
struct Post {
id: u32,
title: String,
body: String,
user_id: u32,
}
match client
.get::<Post>("https://jsonplaceholder.typicode.com/posts/1", None, None)
.await
{
Ok(response) => {
let post = &response.body;
println!(" ✅ Status: {}", response.status);
println!(" 📝 Post #{}: {}", post.id, post.title);
println!(" Body: {}...", &post.body[..60.min(post.body.len())]);
}
Err(e) => println!(" ❌ Error: {}", e),
}
println!();
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ All 8 examples completed! ║");
println!("╚══════════════════════════════════════════════════════════════╝");
}