CosmoHttpClient 4.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package CosmoHttpClient --version 4.0.0
                    
NuGet\Install-Package CosmoHttpClient -Version 4.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CosmoHttpClient" Version="4.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CosmoHttpClient" Version="4.0.0" />
                    
Directory.Packages.props
<PackageReference Include="CosmoHttpClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CosmoHttpClient --version 4.0.0
                    
#r "nuget: CosmoHttpClient, 4.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CosmoHttpClient@4.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CosmoHttpClient&version=4.0.0
                    
Install as a Cake Addin
#tool nuget:?package=CosmoHttpClient&version=4.0.0
                    
Install as a Cake Tool

CosmoHttpClient

CosmoHttpClient is a .NET 10 HTTP client library built clean-sheet to outperform System.Net.Http.HttpClient while still offering the convenience layer (cookies, redirects, retries, response cache, decompression, NDJSON, telemetry) people expect from an everyday client.

Two layers, one recommended surface:

  • FastClient / FastH2Client / FastH3Client — span-based codecs on arena buffers, per-core sharded H/1.1 pool, multiplexed H/2 connections, QUIC-multiplexed H/3 with QPACK dynamic table. Zero per-op allocation on the data plane. Beats HttpClient on every measured benchmark.
  • FastFeatureClient — wraps FastClient with an opt-in handler pipeline: DecompressionHandler, CookieHandler, RedirectHandler, RetryHandler, ResponseCacheHandler, TelemetryHandler. Pay only for the features you turn on.

Also in tree: CosmoWebSocket (RFC 6455), Grpc/* framing primitives, and a tools/PerfGate runner that enforces BDN-measured ratio + allocation rules on every change.

Requirements

  • .NET SDK 10.0+
  • For HTTP/3: platform QUIC support (System.Net.Quic / MsQuic availability)

The library targets net10.0.

Repository layout

Path Purpose
src/CosmoHttpClient/Fast/ FastClient + HTTP/1.1 connection pool, span-based H1 codec
src/CosmoHttpClient/Fast/Http2/ FastH2Client, HPACK, frame layer, multiplexed H/2 connection
src/CosmoHttpClient/Fast/Http3/ FastH3Client, QPACK, QUIC stream pool
src/CosmoHttpClient/Fast/Features/ Handler pipeline: FastFeatureClient, Decompression/Cookie/Redirect/Retry/ResponseCache/Telemetry handlers, JSON + NDJSON extensions
src/CosmoHttpClient/Connections/ Socket / TLS / SOCKS5 transport — used by CosmoWebSocket
src/CosmoHttpClient/WebSockets/ CosmoWebSocket (RFC 6455)
src/CosmoHttpClient/Grpc/ gRPC framing primitives
tests/CosmoHttpClient.Tests xUnit suite (~410 tests)
samples/CosmoHttpClient.Sample Runnable sample app
benchmarks/CosmoHttpClient.Benchmarks BDN benchmarks
benchmarks/perf-targets.json Perf-gate rules consumed by tools/PerfGate
tools/PerfGate BDN runner + JSON parser; exits non-zero on regression

Build, test, run

dotnet build --nologo
dotnet test --nologo --no-build

dotnet run --project samples/CosmoHttpClient.Sample
dotnet run --project samples/CosmoHttpClient.Sample -- --h2 https://www.cloudflare.com/
dotnet run --project samples/CosmoHttpClient.Sample -- --h3 https://www.cloudflare.com/

Run the perf gate (full BDN sweep + rule validation, ~15-20 min):

dotnet run -c Release --project tools/PerfGate
# Or evaluate against existing artifacts (no BDN re-run):
dotnet run -c Release --project tools/PerfGate -- --results gate-artifacts/results

Quick start — FastClient (HTTP/1.1)

using CosmoHttpClient.Fast;

await using var client = new FastClient();
await using var resp = await client.GetAsync(new Uri("https://api.example.com/v1/things"));
Console.WriteLine($"{resp.StatusCode}: {Encoding.UTF8.GetString(resp.Body.Span)}");

POST with JSON body and headers:

private static readonly HeaderPair[] AuthHeaders = {
    new("User-Agent", "myapp/1.0"),
    new("Content-Type", "application/json"),
    new("Authorization", $"Bearer {token}"),
};

var body = JsonSerializer.SerializeToUtf8Bytes(new { name = "widget" });
await using var resp = await client.PostAsync(uri, body, AuthHeaders);

Streaming a large response via PipeReader (Content-Length and chunked both supported):

await using var resp = await client.GetStreamAsync(new Uri("https://example.com/big.bin"));
var rdr = resp.BodyReader;
while (true)
{
    var read = await rdr.ReadAsync();
    foreach (var seg in read.Buffer) await output.WriteAsync(seg);
    rdr.AdvanceTo(read.Buffer.End);
    if (read.IsCompleted) break;
}

Lifetime contract: a streaming response borrows a pool connection until disposed. Drain-then-dispose returns the connection; dispose-without-drain marks the connection broken (wire state is unknown) and the pool drops it. Set FastClientOptions.BackgroundDrainOnDispose = true to opt into a fire-and-forget drain that recovers the connection at the cost of a background task per abandoned response.

FastClient exposes GetAsync, GetStreamAsync, PostAsync, and SendAsync / SendStreamAsync(method, uri, body, headers, ct) for arbitrary verbs. Buffered response body is ReadOnlyMemory<byte> aliasing the connection's arena, valid until the response is disposed. Headers iterate via a zero-allocation Http1HeaderEnumerator.

Quick start — FastH2Client (HTTP/2)

using CosmoHttpClient.Fast.Http2;

await using var h2 = new FastH2Client();
await using var res = await h2.GetAsync(new Uri("https://www.cloudflare.com/"));
Console.WriteLine($"H/2 {res.StatusCode}, {res.Body.Length} bytes");

One multiplexed connection per origin (h2c plain or h2 over TLS+ALPN), span-based HPACK + frame layer, friendly GetAsync / PostAsync.

Quick start — FastH3Client (HTTP/3)

using CosmoHttpClient.Fast.Http3;

await using var h3 = new FastH3Client();
try
{
    await using var res = await h3.GetAsync(new Uri("https://www.cloudflare.com/"));
    Console.WriteLine($"H/3 {res.StatusCode}, {res.Body.Length} bytes");
}
catch (FastH3NotSupportedException) { /* QUIC not available */ }

QUIC stream multiplexing, static + dynamic QPACK. Throws FastH3NotSupportedException on platforms without QUIC (e.g. macOS today).

FastFeatureClient — opt-in handler pipeline

Wrap a FastClient with the handlers you actually want. Empty handler list = bare FastClient performance. Anything beyond is pay-as-you-go.

using CosmoHttpClient.Fast.Features;

await using var client = new FastFeatureClient(new FastFeatureClientOptions
{
    Handlers = new IFastFeatureHandler[]
    {
        new TelemetryHandler(new ActivitySourceTelemetry()),  // outermost
        new ResponseCacheHandler(),                           // RFC 7234 / 9111
        new DecompressionHandler(),                           // gzip / deflate / br / zstd
        new CookieHandler(),                                  // RFC 6265
        new RedirectHandler(),                                // 301/302/303 → GET, 307/308 preserve
        new RetryHandler(),                                   // 408/429/5xx, idempotent-only by default
    },
});

await using var resp = await client.GetAsync(new Uri("https://api.example.com/"));

JSON / NDJSON helpers compose on top of the same client:

var widget = await client.GetJsonAsync(uri, MyJsonContext.Default.Widget);

await foreach (var line in client.GetNdjsonAsync(uri, MyJsonContext.Default.LogLine, ct))
    Process(line);

Handler ordering

Composition is order-sensitive — the first handler in the list runs outermost. Recommended layering (outer → inner):

Telemetry → ResponseCache → Decompression → Cookies → Redirects → Retries → terminal transport

Why this order:

  • Telemetry outermost so spans cover everything, including retries / redirects.
  • ResponseCache outside Decompression so the cache stores wire bytes (so the same entry serves clients with different Accept-Encoding).
  • Decompression outside Cookies / Redirects so subsequent handlers see plain bodies.
  • Retries innermost (around the transport) so a retried request does not loop the redirect / cookie machinery.

You can deviate when you have a reason — the framework just hands you control.

CosmoWebSocket

using CosmoHttpClient.WebSockets;

await using var ws = await CosmoWebSocket.ConnectAsync("wss://example.com/socket");
await ws.SendAsync(payload, CosmoWebSocketMessageType.Binary, endOfMessage: true, ct);

Optional permessage-deflate, ping/pong keepalive, RFC 6455 close handshake. Built on the same Connections/ socket + TLS + SOCKS5 plumbing as the rest of the library.

Performance

Latest BDN sweep on Apple M1 / .NET 10 / Kestrel loopback. Cosmo / HttpClient ratios — values < 1.00 mean Cosmo is faster.

Benchmark Cosmo HttpClient Ratio
Data plane (write+parse, in-memory) 151 ns / 0 B n/a (vs naive) 0.74× of naive baseline
H1.1 single connection (1 KiB GET) 47.2 µs / 771 B 51.4 µs / 3.4 KB 0.92× / 4.4× less alloc
H1.1 pooled, single-threaded 42.9 µs / 946 B 51.7 µs / 3.4 KB 0.83× / 3.6× less alloc
H1.1 pooled, 8 workers × 64 reqs 4.93 ms / 187 KB 4.88 ms / 1.6 MB 1.01× / 8.7× less alloc
Friendly FastClient API (1 KiB GET) 43.4 µs / 1382 B 51.1 µs / 3.4 KB 0.85× / 2.5× less alloc
Friendly FastClient over HTTPS 55.3 µs / 3022 B 63.6 µs / 4.95 KB 0.87× / 1.7× less alloc
Friendly FastClient streaming 4 MiB 1.08 ms / 101 KB 1.09 ms / 100 KB 0.87× / parity

The architectural promise — 0 alloc/op on the data plane in steady state — is asserted by FastH1AllocDiagnosticTests on every test run, independent of BDN's amortization noise.

Releasing

Releases publish via .github/workflows/publish.yml on any pushed tag matching v*.

git tag v4.0.0
git push origin v4.0.0

The workflow strips the leading v, builds Release, runs the full test suite, packs CosmoHttpClient.<version>.nupkg + .snupkg, and pushes both to nuget.org via --skip-duplicate. The .snupkg carries SourceLink metadata so consumers can step into the library source from their debugger.

Configure once on GitHub: Settings → Secrets and variables → Actions → New repository secret named NUGET_API_KEY with a nuget.org API key scoped to CosmoHttpClient.

License

MIT — see LICENSE.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on CosmoHttpClient:

Package Downloads
CosmoBlob.Client

CosmoHttpClient-backed client for CosmoKvD's /blobs/{key} surface. Drop into any .NET 10 app that wants an opaque blob store; pair with a thin IBlobStore adapter when used with CosmoMailServer. v1.0.0 swaps System.Net.Http.HttpClient for CosmoHttpClient's FastAutoClient (HTTP/1.1+2+3 auto-negotiation, span-based hot path).

CosmoMail

Lightweight .NET SMTP and IMAP client library with MIME generation, templating, attachments, inline images, and STARTTLS support.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
5.1.1 91 5/29/2026
5.1.0 1,093 5/24/2026
5.0.5 243 5/21/2026
5.0.4 89 5/21/2026
5.0.3 102 5/18/2026
5.0.2 109 5/18/2026
5.0.1 90 5/18/2026
5.0.0 105 5/10/2026
4.0.0 105 5/10/2026
3.0.0 99 5/9/2026
2.0.0 97 5/9/2026
1.0.0 99 5/8/2026