|
cofetch
Chainable, high-performance async HTTP client for C++ event loops
|
Requests build as a chain, setters flow off request() and the HTTP verb fires the transfer, without blocking the thread:
On C++20 that includes coroutines: dependent requests in linear code, no nesting:
#include <cofetch.h>.asio::io_context. Drive it with run(), or poll() it from a busy loop that must never block.co_await interface..curl([](CURL* h) { ... }) exposes the raw handle per request.Same workload for every client: 20,000 GETs against a local nginx. cpr and cpp-httplib are synchronous (one request per thread); cofetch keeps 100 in flight requests on a single thread, and wins every scenario: +35% single-thread throughput over the fastest sync client, +31% with one event loop per core against equal-sized thread pools, +16% on sequential chains driven from a busy-poll loop.
<picture> <source media="(prefers-color-scheme: dark)" srcset="docs/benchmark-dark.svg"> </picture>
Exact numbers, environment, and how to reproduce: bench/README.md.
On C++20 the same flow reads linearly with co_await (examples/example_coroutine.cpp); the full set lives in examples/. Every public symbol at a glance: the API reference cheatsheet.
Prefer a plain value? cofetch::Request holds the same fields and fires later via http.async_perform(std::move(req), token).
Requirements:
co_await interface needs C++20)-DCOFETCH_USE_BOOST_ASIO=ONcofetch is in the vcpkg registry; asio and curl come along as dependencies, so this is the turnkey path:
cofetch does not impose an ASIO on consumers: point it at yours (any include path providing <asio.hpp>), or enable the vendored submodule with -DCOFETCH_USE_VENDORED_ASIO=ON.
Copy include/cofetch.h, add asio to your include path, link libcurl.
Client per io_context thread by design, no locks on the hot path. The client must outlive its in-flight requests.