use api_bones_reqwest::{RequestBuilderExt, ResponseExt};
#[tokio::main]
#[allow(clippy::significant_drop_tightening)]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== RequestBuilderExt ===\n");
let _req = reqwest::Client::new()
.post("https://api.example.com/orders")
.with_request_id("req-abc-123")
.with_idempotency_key("idem-xyz-789")
.with_bearer_token("eyJhbGciOiJIUzI1NiJ9.example");
println!("Builder with X-Request-Id, Idempotency-Key, Authorization: Bearer — built ok");
println!("\n=== ResponseExt::rate_limit_info ===\n");
let mut server = mockito::Server::new_async().await;
let _mock = server
.mock("GET", "/items")
.with_status(200)
.with_header("x-ratelimit-limit", "100")
.with_header("x-ratelimit-remaining", "42")
.with_header("x-ratelimit-reset", "1700000000")
.with_header("retry-after", "5")
.with_body("[]")
.create_async()
.await;
let resp = reqwest::get(format!("{}/items", server.url())).await?;
match resp.rate_limit_info() {
Some(rl) => {
println!(" limit: {}", rl.limit);
println!(" remaining: {}", rl.remaining);
println!(" reset: {}", rl.reset);
println!(" retry_after: {:?}", rl.retry_after);
}
None => println!(" no rate-limit headers"),
}
println!("\n=== ResponseExt::next_page_url ===\n");
let _mock2 = server
.mock("GET", "/paged")
.with_status(200)
.with_header(
"link",
r#"<https://api.example.com/items?after=xyz>; rel="next", <https://api.example.com/items>; rel="first""#,
)
.with_body("[]")
.create_async()
.await;
let resp2 = reqwest::get(format!("{}/paged", server.url())).await?;
println!(" next page: {:?}", resp2.next_page_url());
println!("\n=== ResponseExt::problem_json_or_json (success) ===\n");
let _mock3 = server
.mock("GET", "/resource")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(r#"{"id": 1, "name": "example"}"#)
.create_async()
.await;
let resp3 = reqwest::get(format!("{}/resource", server.url())).await?;
let body: serde_json::Value = resp3.problem_json_or_json().await?;
println!(" body: {body}");
println!("\n=== ResponseExt::problem_json_or_json (problem+json error) ===\n");
let _mock4 = server
.mock("GET", "/missing")
.with_status(404)
.with_header("content-type", "application/problem+json")
.with_body(
r#"{"type":"urn:api-bones:error:resource-not-found","title":"Resource Not Found","status":404,"detail":"item 99 not found"}"#,
)
.create_async()
.await;
let resp4 = reqwest::get(format!("{}/missing", server.url())).await?;
match resp4.problem_json_or_json::<serde_json::Value>().await {
Ok(v) => println!(" unexpected ok: {v}"),
Err(e) => {
println!(" error status: {}", e.status);
println!(" error detail: {}", e.detail);
}
}
Ok(())
}