rust_api_calling
A clean, idiomatic Rust HTTP client library with one core function that handles all HTTP communication. Built on top of reqwest with automatic JSON serialization via serde.
Features
- Single core function —
make_requesthandles everything;get()andpost()are thin wrappers - Typed responses — Deserialize JSON directly into your Rust structs via generics
- Builder pattern — Configure the client once with
ApiClient::builder(), reuse everywhere - Base URL support — Set it once, then use relative paths like
"/users" - Session management — Automatic XSRF token and cookie handling across requests
- Per-request overrides — Custom timeout, headers, and bearer token per call via
RequestConfig - Strongly-typed errors —
ApiErrorenum with clear variants instead of magic error codes - Structured logging — Built-in tracing integration
- Async/await — Powered by tokio
Installation
Add to your Cargo.toml:
[]
= "0.1.0"
= { = "1", = ["derive"] }
= "1"
= { = "1", = ["full"] }
Quick Start
use ;
use Deserialize;
async
Usage Guide
1. Create the Client
Create one ApiClient and reuse it — it uses connection pooling internally.
use ApiClient;
use Duration;
let client = builder
.base_url // Prepended to all relative paths
.default_timeout // Default timeout for all requests
.default_header // Sent with every request
.session_enabled // Auto-manage cookies & XSRF tokens
.build
.unwrap;
2. GET Requests
use Deserialize;
// Simple GET
let response = client..await?;
println!;
// GET with query parameters
let response = client
.
.await?;
3. POST Requests
use ;
let new_user = CreateUser ;
let response = client
.
.await?;
println!;
4. Per-Request Configuration
Override client defaults for individual requests:
use RequestConfig;
use Duration;
let config = new
.timeout // Custom timeout
.bearer_token // Authorization header
.header; // Custom header
let response = client
.
.await?;
5. Error Handling
All errors are strongly typed via the ApiError enum:
use ApiError;
match client..await
6. Using Raw JSON Responses
If you don't want to define a struct, use serde_json::Value:
let response = client
.
.await?;
// Access fields dynamically
if let Some = response.body.as_array
// Raw body string is also available
println!;
7. Absolute URLs (Bypass Base URL)
You can always pass a full URL to bypass the configured base_url:
// This ignores the base_url and calls the full URL directly
let response = client
.
.await?;
8. Session Management
When session_enabled(true) is set, the client automatically:
- Reads XSRF tokens from response headers (
x-xsrf-token,xsrf-token,x-csrf-token) - Reads cookies from
set-cookieheaders - Attaches them to all subsequent requests
You can also manage sessions manually:
// Set session data manually
client.session.set_xsrf_token;
client.session.set_cookie;
// Read current session data
if let Some = client.session.xsrf_token
// Clear all session data
client.session.clear;
9. The Core Function
All methods delegate to make_request. You can call it directly for full control:
use HttpMethod;
let response = client
.
.await?;
10. Response Object
Every response includes:
let response = client..await?;
response.status; // HTTP status code (u16)
response.headers; // HashMap<String, String>
response.body; // Deserialized body (MyType)
response.raw_body; // Raw response string
response.is_success; // true if 2xx
response.header; // Case-insensitive header lookup
API Reference
ApiClient
| Method | Description |
|---|---|
ApiClient::builder() |
Start building a new client |
.get(url, query, config) |
Perform a GET request |
.post(url, body, config) |
Perform a POST request |
.make_request(method, url, body, query, config) |
The core function — full control |
ApiClientBuilder
| Method | Description |
|---|---|
.base_url(url) |
Set the base URL for all relative paths |
.default_timeout(duration) |
Set default timeout (default: 60s) |
.default_header(key, value) |
Add a header sent with every request |
.session_enabled(bool) |
Enable automatic session/cookie management |
.build() |
Build the ApiClient |
RequestConfig
| Method | Description |
|---|---|
RequestConfig::new() |
Create empty per-request config |
.timeout(duration) |
Override timeout for this request |
.bearer_token(token) |
Set Authorization bearer token |
.header(key, value) |
Add a custom header |
ApiError
| Variant | When |
|---|---|
InvalidUrl(String) |
URL could not be parsed |
NetworkError(reqwest::Error) |
Connection, DNS, or TLS failure |
SerializationError(serde_json::Error) |
JSON serialize/deserialize failure |
HttpError { status, body } |
Server returned non-2xx status |
EmptyResponse |
Server returned empty body |
Timeout |
Request timed out |
Logging
This library uses the tracing crate for structured logging. To see log output, add a subscriber in your application:
// Add to dev-dependencies: tracing-subscriber = { version = "0.3", features = ["env-filter"] }
fmt
.with_env_filter
.init;
Log levels used:
INFO— Request method and URLDEBUG— Query params, request body, response bodyWARN— Empty responsesERROR— Network errors, timeouts, HTTP errors, deserialization failures
Example
A full working example is included in the examples/ directory:
License
Licensed under the MIT License.