Fibre HTTP

Simple, high performance, multi-mode sync/async HTTP/1 and HTTP/2 client.

fibre_http is an HTTP client for Rust that works the same way from async code and from blocking code. You make an AsyncClient or a SyncClient. to_sync() and to_async() turn one into the other for free. Both share one connection pool, so a thread and a task can use the same HTTP/2 connection.

A blocking call does its own I/O on its own thread, so there is no background runtime to start. You can begin a request in async code and read the body on a blocking thread.

It speaks HTTP/1.1 with keep-alive and HTTP/2 with multiplexing. TLS is rustls by default, with native-tls as an option. Proxies, redirects, retries, per-request deadlines and streamed request bodies are built in.

use fibre_http::AsyncClient;

let client = AsyncClient::new();
let page = client.get("https://example.com/").send().await?.text().await?;

let blocking = client.clone().to_sync();
let page = tokio::task::spawn_blocking(move || blocking.get("https://example.com/").send()?.text()).await.unwrap()?;

Requests a second for 64-byte GETs to a local hyper server with N concurrent callers, on an Apple M4 Pro. Higher is better. hyper is the low-level client most Rust HTTP clients are built on, so it is shown as a yardstick and not ranked.

Nfibre_http asyncfibre_http blockingreqwest asyncreqwest blockinghyper (yardstick)
HTTP/1.1142,49843,14935,76226,94542,855
HTTP/1.18141,966132,618127,20582,051146,463
HTTP/1.132169,772124,303171,44485,636174,848
h2c136,04039,50631,80623,83740,714
h2c8102,04984,63071,63177,18783,779
h2c32126,02973,08674,301112,08581,692

Tutorials

Fetch a page from blocking and async codeYou fetch a web page with fibre_http, first from plain blocking code and then from async code. Then you send a request from each kind of code through the same client and see that they share one connection.Set timeouts and handle errorsYou give a fibre_http client a timeout, turn error statuses like 404 into errors you can match on and watch a request to a server that never answers give up on time.Download a file to disk from async codeYou start a download in async code, then hand the response body to a blocking thread that writes it to a file with plain std::io::copy.Send a query, headers and a formYou add query parameters and headers to a GET request and send a form in a POST. httpbin.org echoes back what it received, so you can see exactly what went over the wire.Send and receive JSONYou post a Rust struct as JSON and read the answer back into another struct, using serde on both ends.Follow or stop at redirectsYou follow a chain of three redirects, put a limit on how many a client will follow and turn redirects off so you can read the Location header yourself.Keep cookies between requestsYou turn on a client's cookie store so a cookie one response sets is sent on the requests after it, the way a browser keeps you logged in.Read compressed responsesYou turn on gzip support so the server can send a compressed body and you still read plain text. Then you turn decoding off to see the compressed bytes that came over the network.Send many requests over one HTTP/2 connectionYou check that fibre_http picked HTTP/2 for a server that offers it, then send 20 requests at the same time and see that they all share one connection.Stream an upload and read a download in chunksYou upload a file straight from disk without reading it into memory first, then read a download piece by piece as it arrives.