Thanks to visit codestin.com
Credit goes to github.com

Skip to content
/ frakt Public

Platform-native HTTP client (NSURLSession, WinHTTP/BITS, Reqwest, Cronet)

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

bbqsrc/frakt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

frakt

High-performance, async-first HTTP client for Rust. Cross-platform with native backends: NSURLSession on Apple platforms, WinHTTP on Windows, and Reqwest elsewhere.

Crates.io Documentation License

Features

  • Async/await with tokio - Full async support, no blocking APIs
  • All HTTP methods - GET, POST, PUT, DELETE, PATCH, HEAD
  • WebSocket support - NSURLSessionWebSocketTask/WinHTTP integration
  • File operations - Uploads/downloads with progress tracking
  • Background sessions - Downloads that survive app suspension (iOS)
  • Cookie management - NSHTTPCookieStorage/cookie_store integration
  • Proxy configuration - HTTP/HTTPS/SOCKS proxy support
  • Authentication - Basic, Bearer, and Custom authentication
  • TLS/Certificate handling - Server trust challenge support
  • Streaming responses - AsyncRead for memory-efficient large downloads
  • Multipart form data - File uploads with form fields
  • Zero-overhead - Direct objc2 bindings with minimal abstractions

Installation

Add this to your Cargo.toml:

[dependencies]
frakt = "0.1"

Platform Support

  • macOS 10.15+ (Foundation backend using NSURLSession)
  • iOS 13.0+ (Foundation backend using NSURLSession)
  • Windows (WinHTTP backend)
  • Linux/Unix (Reqwest backend)
  • Rust 1.86+

The library automatically selects the best native backend for each platform. You can also manually specify a backend using BackendType if needed.

Quick Start

use frakt::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a client
    let client = Client::builder()
        .user_agent("MyApp/1.0")
        .timeout(std::time::Duration::from_secs(30))
        .build()?;

    // Make a GET request
    let response = client
        .get("https://httpbin.org/json")
        .header("Accept", "application/json")
        .send()
        .await?;

    println!("Status: {}", response.status());
    let json: serde_json::Value = response.json().await?;
    println!("Response: {}", json);

    Ok(())
}

Examples

Basic HTTP Requests

// GET request
let response = client.get("https://api.example.com/data").send().await?;

// POST with JSON
let response = client
    .post("https://api.example.com/users")
    .header("Content-Type", "application/json")
    .body(r#"{"name": "John", "email": "[email protected]"}"#)
    .send()
    .await?;

Authentication

use frakt::Auth;

// Basic authentication
let response = client
    .get("https://api.example.com/protected")?
    .auth(Auth::basic("user", "pass"))
    .send()
    .await?;

// Bearer token
let response = client
    .get("https://api.example.com/protected")?
    .auth(Auth::bearer("your-token"))
    .send()
    .await?;

File Downloads with Progress

let response = client
    .get("https://example.com/large-file.zip")?
    .progress(|downloaded, total| {
        if let Some(total) = total {
            let percent = (downloaded as f64 / total as f64) * 100.0;
            println!("Progress: {:.1}%", percent);
        }
    })
    .send()
    .await?;

// Download directly to file
client
    .download("https://example.com/file.zip")
    .to_file("./downloads/file.zip")
    .progress(|downloaded, total| {
        println!("Downloaded: {} / {:?} bytes", downloaded, total);
    })
    .send()
    .await?;

WebSocket

use frakt::{Message, CloseCode};

let websocket = client
    .websocket()
    .maximum_message_size(1024 * 1024)
    .connect("wss://echo.websocket.org")
    .await?;

// Send message
websocket.send(Message::text("Hello, WebSocket!")).await?;

// Receive message
let message = websocket.receive().await?;
match message {
    Message::Text(text) => println!("Received: {}", text),
    Message::Binary(data) => println!("Received {} bytes", data.len()),
}

// Close connection
websocket.close(CloseCode::Normal, Some("Goodbye"));

Cookies

let client = Client::builder()
    .use_cookies(true)
    .build()?;

// Cookies are automatically managed
let response = client.get("https://httpbin.org/cookies/set/session/abc123")?.send().await?;
let response = client.get("https://httpbin.org/cookies")?.send().await?; // Cookie sent automatically

Proxy Configuration

let client = Client::builder()
    .http_proxy("proxy.example.com", 8080)
    .proxy_auth("username", "password")
    .build()?;

Streaming Large Responses

use tokio::io::AsyncReadExt;

let response = client.get("https://example.com/large-file")?.send().await?;
let mut stream = response.stream();
let mut buffer = [0u8; 8192];

while let bytes_read = stream.read(&mut buffer).await? {
    if bytes_read == 0 { break; }
    // Process chunk
    process_chunk(&buffer[..bytes_read]);
}

Available Examples

Run examples with cargo run --example <name>:

  • auth - Authentication methods (Basic, Bearer, Custom)
  • cookies - Cookie management and automatic handling
  • download - Basic file downloads
  • file_download - Direct-to-file downloads with progress
  • file_upload - File uploads using upload builder
  • multipart - Multipart form data uploads
  • progress - Progress tracking for downloads
  • proxy - Proxy configuration (HTTP/HTTPS/SOCKS)
  • streaming - Streaming large responses with AsyncRead
  • upload_task - Upload tasks with progress tracking
  • websocket - WebSocket client usage
  • background_download - Background downloads (iOS)

Architecture

This library provides a unified HTTP client interface with platform-native backends. On Apple platforms, it uses direct Rust bindings to NSURLSession via objc2. On Windows, it uses WinHTTP APIs. On other platforms, it uses the battle-tested Reqwest library. Key design principles:

  • Async-only: Built for tokio, no blocking APIs
  • Zero-overhead: Direct native API calls with minimal abstraction
  • Memory efficient: Uses platform-native data types where possible
  • Type safe: All unsafe native API calls are wrapped in safe APIs
  • Rusty: Builder patterns and ergonomic error handling

Error Handling

All errors are mapped to Rust's Result type:

use frakt::Error;

match client.get("https://invalid-url")?.send().await {
    Ok(response) => println!("Success: {}", response.status()),
    Err(Error::InvalidUrl) => println!("Invalid URL"),
    Err(Error::Network(msg)) => println!("Network error: {}", msg),
    Err(Error::Timeout) => println!("Request timed out"),
    Err(e) => println!("Other error: {}", e),
}

Performance

frakt leverages platform-native performance optimizations:

  • HTTP/2 and HTTP/3 support (when available)
  • Connection pooling and keep-alive
  • Automatic compression (gzip, deflate, br)
  • Native TLS implementation
  • Background processing capabilities

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Platform-native HTTP client (NSURLSession, WinHTTP/BITS, Reqwest, Cronet)

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •  

Packages

No packages published