Skip to content

Latest commit

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

api-client

A high-performance, Tower-backed HTTP API client for Rust.

Features

  • Tower Stack: Leverages the Tower ecosystem for middleware (load balancing, retrying, rate limiting, etc.).
  • Audit Logging: Built-in audit layer that logs requests as curl commands and pretty-prints JSON responses.
  • Custom Auditors: Support for custom auditing backends (e.g., Object Storage, custom databases).
  • Concurrency Control: Optional semaphore-based concurrency limiting.
  • Cookie Support: Automatic cookie management.
  • Retry Logic: Automatic retries for idempotent requests on transient errors.

Installation

Add to your Cargo.toml:

[dependencies]
api-client = { git = "https://github.com/bixority/api-client" }

Usage

use api_client::{APIClient,Method,Headers};#[tokio::main]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{let client = APIClient::new("https://api.example.com".to_string()).timeout_secs(5).max_concurrent(Some(10)).build()?;let headers = Headers::new().content_type("application/json").authorization_bearer("your-token");let response = client.request("/v1/resource",Method::Get,
headers,None,// bodyNone,// query paramsNone,// audit config).await?;if response.status().is_success(){let text = response.text().await?;println!("Response: {}", text);}Ok(())}

Audit Logging

The client includes a powerful auditing layer. By default, if no custom auditor is provided, it logs requests and responses to the standard output using the tracing crate.

Custom Auditor

You can implement the Auditor trait to send audit data to a custom backend. See examples/audit.rs for a complete working example.

use api_client::{Auditor,APIClient,APIClientError};use futures::future::{BoxFuture,FutureExt};use std::sync::Arc;structMyAuditor;implAuditorforMyAuditor{fnwrite_audit_data(&self,path:&str,data:&[u8],) -> BoxFuture<'static,Result<(),APIClientError>>{let data = data.to_vec();let path = path.to_string();asyncmove{println!("Writing audit data to {}: {} bytes", path, data.len());// In a real implementation, you would write to a database or object storageOk(())}.boxed()}}// Enable the custom auditor in the clientlet client = APIClient::new(base_url).with_auditor(Arc::new(MyAuditor)).build()?;

Per-Request Configuration

Audit logging can be configured per request using AuditConfig. This allows you to name the audit entry or mute the response body (crucial for large responses or streaming).

use api_client::AuditConfig;// Name the audit entry and disable response body logginglet audit = AuditConfig::new("my-request").mute_response();let response = client.request("/v1/resource",Method::Get,
headers,None,None,Some(audit)).await?;

When an auditor is used, the client generates structured paths for audit files: YYYY/MM/DD/{audit_name}/{uri_path}/{METHOD}_{YYMMDD_HHMMSS_ffffff}_{request_id}_{request|response}.txt

Streaming

To stream a response body, you MUST mute the response audit using AuditConfig::mute_response(). This prevents the client from buffering the entire body to log it.

use api_client::{APIClient,Method,Headers,AuditConfig};use futures::StreamExt;let audit = AuditConfig::new("large-download").mute_response();let response = client.request("/download",Method::Get,Headers::new(),None,None,Some(audit)).await?;letmut stream = response.bytes_stream()?;whileletSome(chunk_result) = stream.next().await{let chunk = chunk_result?;println!("Received {} bytes", chunk.len());}

License

GPL-3.0-only

About

API client

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages