qubit-http

General-purpose HTTP infrastructure for Rust with unified client semantics, secure logging, and built-in SSE decoding

Rust CI Coverage Crates.io Docs.rs Rust License

Documentation: User Guide | API Reference

qubit-http is a production-oriented Rust HTTP infrastructure crate for building API clients with consistent behavior across services.

It builds on reqwest and provides the common pieces most API clients need: request construction, timeouts, retries, cancellation, streaming responses, SSE, logging, and unified errors.

Why Use It

Use qubit-http when you need:

For full examples and advanced options, read the User Guide.

Installation

[dependencies]
qubit-http = "0.8"
http = "1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Some examples in the user guide use optional helper crates such as serde, serde_json, futures-util, and qubit-config.

Quick Start

This example uses httpbin.org, so you can run it without starting a local test server.

use http::Method;
use qubit_http::{HttpClientFactory, HttpClientOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut options = HttpClientOptions::new();
    options.set_base_url("https://httpbin.org")?;
    options.add_header("x-client-id", "demo")?;

    let client = HttpClientFactory::new().create(options)?;

    let request = client
        .request(Method::GET, "/anything")
        .query_param("from", "readme")
        .build();

    let mut response = client.execute(request).await?;
    println!("status = {}", response.status());
    println!("text = {}", response.text().await?);
    Ok(())
}

Logging Sanitization

HTTP TRACE logs are sanitized before they are emitted. The default policy masks URL userinfo/fragments, sensitive headers, query parameters, and JSON/form/multipart body fields with shared field matching and mask levels. The built-in names and mask levels come from qubit_sanitize::SensitiveFields. Unsupported bodies without a structured or textual Content-Type are redacted instead of being logged raw. Multipart file parts and malformed, missing-boundary, or truncated multipart bodies are redacted as well. You can extend the policy when a service uses custom secret names. Names are matched case-insensitively across common styles such as access_token, access-token, and accessToken:

use qubit_http::{HttpClientFactory, HttpClientOptions};
use qubit_sanitize::SensitivityLevel;

let mut options = HttpClientOptions::new();
options.logging.enabled = true;
options.logging.log_request_body = true;
options
    .log_sanitize_policy
    .sensitive_headers
    .insert("x-api-key", SensitivityLevel::High);
options
    .log_sanitize_policy
    .sensitive_query_params
    .insert("access_token", SensitivityLevel::High);
options
    .log_sanitize_policy
    .sensitive_body_fields
    .insert("password", SensitivityLevel::Secret);

let client = HttpClientFactory::new().create(options)?;

Common Next Steps

TaskRead
Create clients from defaults, options, or configUser Guide
Build JSON, form, multipart, NDJSON, or stream request bodiesUser Guide
Add default headers, header injectors, and interceptorsUser Guide
Configure timeouts, retries, cancellation, and Retry-After handlingUser Guide
Read bytes, text, JSON, streams, or SSE chunksUser Guide
Configure logging sanitization, proxy, redirects, and IPv4-only modeUser Guide
Handle status, transport, timeout, cancellation, decode, and retry errorsUser Guide

Core API At A Glance

TypePurpose
HttpClientFactoryCreates clients from defaults, explicit options, or config.
HttpClientOptionsHolds client-level defaults for base URL, headers, timeouts, retry, logging, proxy, redirects, connection pool, and SSE decoding.
HttpClientExecutes requests and applies headers, injectors, interceptors, retry, logging, and SSE reconnect helpers.
HttpRequestBuilderBuilds method, path, query, headers, body, and request-level overrides.
HttpResponseExposes response metadata and lazy readers for bytes, text, JSON, streams, and SSE.
HttpResponseInterceptorContextLets response interceptors inspect status/method and mutate headers/final URL without breaking success-status invariants.

Project Scope

Contributing

Issues and pull requests are welcome.

Please keep contributions focused and easy to review:

By contributing to this project, you agree that your contribution will be licensed under the same license as the project.

License

Licensed under the Apache License, Version 2.0.