bimp-net 0.0.1

A Rust wrapper around libcurl-impersonate in the shape of hyper.
Documentation

bimp-net

bimp-net is a small Rust wrapper around libcurl-impersonate. It exposes an HTTP client that uses curl_easy_impersonate for browser-like TLS and HTTP transport while returning standard http responses and hyper body streams.

Requirements

Install libcurl-impersonate before building. The build script looks in /usr/local/lib for one of:

  • libcurl-impersonate.dylib
  • libcurl-impersonate.so
  • libcurl-impersonate.a

The command-line curl-impersonate wrapper alone is not enough; the linked library must export curl_easy_impersonate.

Collected Responses

Use send_collect for small responses that can be buffered in memory.

use bimp_net::{Client, Config, RedirectPolicy};
use http::{Method, Request};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(Config {
        impersonation_target: "chrome136".to_string(),
        redirect_policy: RedirectPolicy::Follow,
        ..Config::default()
    });

    let request = Request::builder()
        .method(Method::GET)
        .uri("https://example.com/")
        .body(None)?;
    let response = client.send_collect(request)?;

    println!("{} {}", response.status, response.effective_url);
    Ok(())
}

Streaming Responses

Use send when the caller should consume the response body incrementally.

use bimp_net::{Client, Config};
use http::Request;
use http_body_util::{BodyExt, Empty, Full};
use hyper::body::Bytes;

async fn run() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(Config::default());
    let request = Request::builder()
        .uri("https://example.com/")
        .body(Empty::<Bytes>::new())?;

    let mut response = client.send(request).await?;
    while let Some(frame) = response.body_mut().frame().await {
        if let Some(bytes) = frame?.data_ref() {
            println!("received {} bytes", bytes.len());
        }
    }

    let request = Request::builder()
        .method("POST")
        .uri("https://example.com/")
        .body(Full::new(Bytes::from_static(b"hello")))?;
    let _response = client.send(request).await?;

    Ok(())
}

Configuration

Config::default() uses the chrome136 impersonation target, 10 second connect timeout, 30 second request timeout, no redirect following, and libcurl-impersonate default headers enabled.

Set default_headers to false if you want to provide all request headers yourself. When decoded response bodies are returned, content-encoding, content-length, and transfer-encoding headers are removed because they no longer describe the body bytes delivered to Rust.