Skip to content

Commit bdf8889

Browse files
vkuttypclaude
andcommitted
v2.5.6: CosmoKvHttp client supports Endpoint=unix:///path UDS connections
Co-located clients (mail-server containers, CLI tools running on the same host as cosmokvd) can now bypass TCP loopback by setting their connection string to `Endpoint=unix:///var/run/cosmokvd.sock;...`. Saves the per-call socket-buffer copies + TCP framing — typically 20-40% lower latency on local IPC. Implementation: CosmoKvHttpConnection inspects the Endpoint prefix at construction time. If it starts with `unix://`, a SocketsHttpHandler with a ConnectCallback is wired up, returning a NetworkStream over a freshly-connected UnixDomainSocketEndPoint. HttpClient gets a sentinel `http://cosmokvd-uds/` BaseAddress (the host portion is irrelevant because ConnectCallback short-circuits DNS/TCP). Backwards compatible — TCP endpoints work exactly as before. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1d38ce3 commit bdf8889

2 files changed

Lines changed: 43 additions & 5 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
<Authors>vkuttyp</Authors>
88
<PackageLicenseExpression>MIT</PackageLicenseExpression>
99
<RepositoryUrl>https://github.com/vkuttyp/CosmoSQLClient-Dotnet</RepositoryUrl>
10-
<Version>2.5.5</Version>
10+
<Version>2.5.6</Version>
1111
</PropertyGroup>
1212
</Project>

src/CosmoSQLClient.CosmoKvHttp/CosmoKvHttpConnection.cs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Net;
22
using System.Net.Http.Headers;
33
using System.Net.Http.Json;
4+
using System.Net.Sockets;
45
using System.Runtime.CompilerServices;
56
using System.Text.Json;
67
using CosmoSQLClient.Core;
@@ -47,14 +48,51 @@ public CosmoKvHttpConnection(CosmoKvHttpConfiguration config, HttpClient http)
4748
public CosmoKvHttpConnection(CosmoKvHttpConfiguration config)
4849
{
4950
_config = config;
50-
_http = new HttpClient
51+
_http = BuildHttpClient(config);
52+
_http.DefaultRequestHeaders.Authorization =
53+
new AuthenticationHeaderValue("Bearer", config.AuthToken);
54+
_ownsHttp = true;
55+
}
56+
57+
/// <summary>
58+
/// Build the underlying <see cref="HttpClient"/>. When
59+
/// <c>config.Endpoint</c> starts with <c>unix://</c> we route the
60+
/// connection over a Unix Domain Socket instead of TCP — saves the
61+
/// per-call loopback overhead when cosmokvd runs on the same host
62+
/// (the typical co-located mail-server deployment). The path after
63+
/// <c>unix://</c> is the absolute socket path on disk. The HTTP
64+
/// virtual host portion of requests becomes irrelevant since
65+
/// <see cref="SocketsHttpHandler.ConnectCallback"/> short-circuits
66+
/// the DNS/TCP machinery — we use a sentinel <c>cosmokvd-uds</c>
67+
/// host so any logging is recognisable.
68+
/// </summary>
69+
private static HttpClient BuildHttpClient(CosmoKvHttpConfiguration config)
70+
{
71+
const string UnixPrefix = "unix://";
72+
if (config.Endpoint.StartsWith(UnixPrefix, StringComparison.OrdinalIgnoreCase))
73+
{
74+
string socketPath = config.Endpoint.Substring(UnixPrefix.Length);
75+
var handler = new SocketsHttpHandler
76+
{
77+
ConnectCallback = async (ctx, ct) =>
78+
{
79+
var ep = new UnixDomainSocketEndPoint(socketPath);
80+
var sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
81+
await sock.ConnectAsync(ep, ct).ConfigureAwait(false);
82+
return new NetworkStream(sock, ownsSocket: true);
83+
},
84+
};
85+
return new HttpClient(handler)
86+
{
87+
BaseAddress = new Uri("http://cosmokvd-uds/"),
88+
Timeout = config.Timeout,
89+
};
90+
}
91+
return new HttpClient
5192
{
5293
BaseAddress = new Uri(config.Endpoint),
5394
Timeout = config.Timeout,
5495
};
55-
_http.DefaultRequestHeaders.Authorization =
56-
new AuthenticationHeaderValue("Bearer", config.AuthToken);
57-
_ownsHttp = true;
5896
}
5997

6098
public CosmoKvHttpConnection(string connectionString)

0 commit comments

Comments
 (0)