Files
git.stella-ops.org/src/AirGap/StellaOps.AirGap.Policy/StellaOps.AirGap.Policy/EgressHttpClientFactory.cs
StellaOps Bot f46bde5575 save progress
2026-01-02 15:52:55 +02:00

94 lines
4.5 KiB
C#

using System;
using System.Net.Http;
namespace StellaOps.AirGap.Policy;
/// <summary>
/// Provides helpers for creating <see cref="HttpClient"/> instances that respect the configured <see cref="IEgressPolicy"/>.
/// </summary>
public static class EgressHttpClientFactory
{
/// <summary>
/// Creates an <see cref="HttpClient"/> after validating the supplied egress request against the policy.
/// </summary>
/// <param name="egressPolicy">The policy used to validate outbound requests.</param>
/// <param name="request">Describes the destination and intent for the outbound call.</param>
/// <param name="configure">Optional configuration hook applied to the newly created client.</param>
/// <returns>An <see cref="HttpClient"/> that has been pre-authorised by the policy.</returns>
public static HttpClient Create(IEgressPolicy egressPolicy, EgressRequest request, Action<HttpClient>? configure = null)
{
ArgumentNullException.ThrowIfNull(egressPolicy);
egressPolicy.EnsureAllowed(request);
var client = new HttpClient();
configure?.Invoke(client);
return client;
}
/// <summary>
/// Creates an <see cref="HttpClient"/> from a caller-provided factory after validating the supplied egress request.
/// </summary>
/// <param name="egressPolicy">The policy used to validate outbound requests.</param>
/// <param name="request">Describes the destination and intent for the outbound call.</param>
/// <param name="clientFactory">Factory used to supply a configured client (for example, from IHttpClientFactory).</param>
/// <param name="configure">Optional configuration hook applied to the newly created client.</param>
/// <returns>An <see cref="HttpClient"/> that has been pre-authorised by the policy.</returns>
public static HttpClient Create(
IEgressPolicy egressPolicy,
EgressRequest request,
Func<HttpClient> clientFactory,
Action<HttpClient>? configure = null)
{
ArgumentNullException.ThrowIfNull(egressPolicy);
ArgumentNullException.ThrowIfNull(clientFactory);
egressPolicy.EnsureAllowed(request);
var client = clientFactory();
if (client is null)
{
throw new InvalidOperationException("EgressHttpClientFactory received a null HttpClient from the factory.");
}
configure?.Invoke(client);
return client;
}
/// <summary>
/// Creates and configures an <see cref="HttpClient"/> after validating the supplied egress request against the policy.
/// </summary>
/// <param name="egressPolicy">The policy used to validate outbound requests.</param>
/// <param name="component">Component initiating the request.</param>
/// <param name="destination">Destination that will be contacted.</param>
/// <param name="intent">Intent label describing why the request is needed.</param>
/// <param name="configure">Optional configuration hook applied to the newly created client.</param>
/// <returns>An <see cref="HttpClient"/> that has been pre-authorised by the policy.</returns>
public static HttpClient Create(
IEgressPolicy egressPolicy,
string component,
Uri destination,
string intent,
Action<HttpClient>? configure = null)
=> Create(egressPolicy, new EgressRequest(component, destination, intent), configure);
/// <summary>
/// Creates a configured <see cref="HttpClient"/> using a caller-provided factory after policy validation.
/// </summary>
/// <param name="egressPolicy">The policy used to validate outbound requests.</param>
/// <param name="component">Component initiating the request.</param>
/// <param name="destination">Destination that will be contacted.</param>
/// <param name="intent">Intent label describing why the request is needed.</param>
/// <param name="clientFactory">Factory used to supply a configured client.</param>
/// <param name="configure">Optional configuration hook applied to the newly created client.</param>
/// <returns>An <see cref="HttpClient"/> that has been pre-authorised by the policy.</returns>
public static HttpClient Create(
IEgressPolicy egressPolicy,
string component,
Uri destination,
string intent,
Func<HttpClient> clientFactory,
Action<HttpClient>? configure = null)
=> Create(egressPolicy, new EgressRequest(component, destination, intent), clientFactory, configure);
}