< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Client.KrHttpClientFactory
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Client/KrHttpClientFactory.cs
Tag: Kestrun/Kestrun@2d87023b37eb91155071c91dd3d6a2eeb3004705
Line coverage
0%
Covered lines: 0
Uncovered lines: 72
Coverable lines: 72
Total lines: 176
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 24
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 09/09/2025 - 05:44:24 Line coverage: 0% (0/71) Branch coverage: 0% (0/24) Total lines: 159 Tag: Kestrun/Kestrun@a26a91936c400a7f2324671b2222643fb772438110/13/2025 - 16:52:37 Line coverage: 0% (0/72) Branch coverage: 0% (0/24) Total lines: 176 Tag: Kestrun/Kestrun@10d476bee71c71ad215bb8ab59f219887b5b4a5e 09/09/2025 - 05:44:24 Line coverage: 0% (0/71) Branch coverage: 0% (0/24) Total lines: 159 Tag: Kestrun/Kestrun@a26a91936c400a7f2324671b2222643fb772438110/13/2025 - 16:52:37 Line coverage: 0% (0/72) Branch coverage: 0% (0/24) Total lines: 176 Tag: Kestrun/Kestrun@10d476bee71c71ad215bb8ab59f219887b5b4a5e

Metrics

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Client/KrHttpClientFactory.cs

#LineLine coverage
 1// src/CSharp/Kestrun.Net/KrHttp.cs
 2using System.IO.Pipes;
 3using System.Net;
 4using System.Net.Security;
 5using System.Net.Sockets;
 6
 7namespace Kestrun.Client;
 8
 9/// <summary>
 10/// Factory methods to create HttpClient instances for different transport types.
 11/// </summary>
 12public static class KrHttpClientFactory
 13{
 14    // ---- Internal helper ----------------------------------------------------
 15    private static SocketsHttpHandler CreateHandler(KrHttpClientOptions opts)
 16    {
 017        var handler = CreateBasicHandler(opts);
 18
 19        // Proxy auth wiring if provided
 020        if (opts.Proxy is not null)
 21        {
 022            if (opts.ProxyUseDefaultCredentials)
 23            {
 024                opts.Proxy.Credentials = CredentialCache.DefaultCredentials;
 25            }
 026            else if (opts.Proxy.Credentials is null && opts.Credentials is not null)
 27            {
 28                // If caller didn't set proxy creds explicitly but provided server creds,
 29                // reuse them for the proxy (common IWR behavior).
 030                opts.Proxy.Credentials = opts.Credentials;
 31            }
 32        }
 33
 034        if (opts.IgnoreCertErrors)
 35        {
 036            handler.SslOptions = new SslClientAuthenticationOptions
 037            {
 038                RemoteCertificateValidationCallback = static (sender, certificate, chain, errors) => true
 039            };
 40        }
 41
 042        return handler;
 43    }
 44
 45    /// <summary>
 46    /// Creates a basic SocketsHttpHandler with common options applied.
 47    /// </summary>
 48    /// <param name="opts">The HTTP client options.</param>
 49    /// <returns>A configured SocketsHttpHandler instance.</returns>
 50    private static SocketsHttpHandler CreateBasicHandler(KrHttpClientOptions opts)
 51    {
 052        var effectiveTimeout = (opts.Timeout <= TimeSpan.Zero) ? TimeSpan.FromSeconds(100) : opts.Timeout;
 53
 054        return new SocketsHttpHandler
 055        {
 056            AutomaticDecompression = opts.Decompression,
 057            ConnectTimeout = effectiveTimeout,
 058
 059            // Redirects
 060            AllowAutoRedirect = opts.AllowAutoRedirect,
 061            MaxAutomaticRedirections = Math.Max(1, opts.MaxAutomaticRedirections),
 062
 063            // Cookies/session
 064            UseCookies = opts.Cookies is not null,
 065            CookieContainer = opts.Cookies ?? new CookieContainer(),
 066
 067            // Proxy
 068            UseProxy = opts.UseProxy && opts.Proxy is not null,
 069            Proxy = opts.Proxy,
 070
 071            // Server auth
 072            Credentials = opts.UseDefaultCredentials
 073                    ? CredentialCache.DefaultCredentials
 074                    : opts.Credentials
 075        };
 76    }
 77
 78    /// <summary>
 79    /// Creates an HttpClient with the specified handler, base address, and timeout.
 80    /// </summary>
 81    /// <param name="handler">The HTTP message handler.</param>
 82    /// <param name="baseAddress">The base address for the HTTP client.</param>
 83    /// <param name="timeout">The timeout for HTTP requests.</param>
 84    /// <returns>A configured HttpClient instance.</returns>
 85    private static HttpClient MakeClient(HttpMessageHandler handler, Uri baseAddress, TimeSpan timeout)
 086        => new(handler)
 087        {
 088            Timeout = (timeout <= TimeSpan.Zero) ? TimeSpan.FromSeconds(100) : timeout,
 089            BaseAddress = baseAddress
 090        };
 91
 92    // ---- Named Pipe ---------------------------------------------------------
 93    /// <summary>Create an HttpClient that talks HTTP over a Windows Named Pipe.</summary>
 94    public static HttpClient CreateNamedPipeClient(string pipeName, TimeSpan timeout)
 095        => CreateNamedPipeClient(pipeName, timeout, ignoreCertErrors: false);
 96
 97    /// <summary>Create an HttpClient that talks HTTP over a Windows Named Pipe (legacy overload).</summary>
 98    public static HttpClient CreateNamedPipeClient(string pipeName, TimeSpan timeout, bool ignoreCertErrors)
 99    {
 0100        var opts = new KrHttpClientOptions { Timeout = timeout, IgnoreCertErrors = ignoreCertErrors };
 0101        return CreateNamedPipeClient(pipeName, opts);
 102    }
 103
 104    /// <summary>Create an HttpClient that talks HTTP over a Windows Named Pipe (full options).</summary>
 105    public static HttpClient CreateNamedPipeClient(string pipeName, KrHttpClientOptions opts)
 106    {
 0107        if (string.IsNullOrWhiteSpace(pipeName))
 108        {
 0109            throw new ArgumentNullException(nameof(pipeName));
 110        }
 111
 0112        var h = CreateHandler(opts);
 113
 114        // capture pipeName in the lambda (works on .NET 6/7/8)
 0115        h.ConnectCallback = (ctx, ct) =>
 0116        {
 0117            var stream = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
 0118            stream.Connect();
 0119            return new ValueTask<Stream>(stream);
 0120        };
 121
 0122        return MakeClient(h, new Uri("http://localhost"), opts.Timeout);
 123    }
 124
 125    // ---- Unix Domain Socket -------------------------------------------------
 126    /// <summary>Create an HttpClient that talks HTTP over a Unix Domain Socket.</summary>
 127    public static HttpClient CreateUnixSocketClient(string socketPath, TimeSpan timeout)
 0128        => CreateUnixSocketClient(socketPath, timeout, ignoreCertErrors: false);
 129
 130    /// <summary>Create an HttpClient that talks HTTP over a Unix Domain Socket (legacy overload).</summary>
 131    public static HttpClient CreateUnixSocketClient(string socketPath, TimeSpan timeout, bool ignoreCertErrors)
 132    {
 0133        var opts = new KrHttpClientOptions { Timeout = timeout, IgnoreCertErrors = ignoreCertErrors };
 0134        return CreateUnixSocketClient(socketPath, opts);
 135    }
 136
 137    /// <summary>Create an HttpClient that talks HTTP over a Unix Domain Socket (full options).</summary>
 138    public static HttpClient CreateUnixSocketClient(string socketPath, KrHttpClientOptions opts)
 139    {
 0140        if (string.IsNullOrWhiteSpace(socketPath))
 141        {
 0142            throw new ArgumentNullException(nameof(socketPath));
 143        }
 144
 0145        var h = CreateHandler(opts);
 146
 0147        h.ConnectCallback = (ctx, ct) =>
 0148        {
 0149            var sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
 0150            sock.Connect(new UnixDomainSocketEndPoint(socketPath));
 0151            return new ValueTask<Stream>(new NetworkStream(sock, ownsSocket: true));
 0152        };
 153
 0154        return MakeClient(h, new Uri("http://localhost"), opts.Timeout);
 155    }
 156
 157    // ---- TCP (HTTP/HTTPS) ---------------------------------------------------
 158    /// <summary>Classic TCP HttpClient (normal HTTP/S).</summary>
 159    public static HttpClient CreateTcpClient(Uri baseUri, TimeSpan timeout)
 0160        => CreateTcpClient(baseUri, timeout, ignoreCertErrors: false);
 161
 162    /// <summary>Classic TCP HttpClient (normal HTTP/S, legacy overload).</summary>
 163    public static HttpClient CreateTcpClient(Uri baseUri, TimeSpan timeout, bool ignoreCertErrors)
 164    {
 0165        var opts = new KrHttpClientOptions { Timeout = timeout, IgnoreCertErrors = ignoreCertErrors };
 0166        return CreateTcpClient(baseUri, opts);
 167    }
 168
 169    /// <summary>Classic TCP HttpClient (normal HTTP/S, full options).</summary>
 170    public static HttpClient CreateTcpClient(Uri baseUri, KrHttpClientOptions opts)
 171    {
 0172        ArgumentNullException.ThrowIfNull(baseUri);
 0173        var h = CreateHandler(opts);
 0174        return MakeClient(h, baseUri, opts.Timeout);
 175    }
 176}