Docs

Koto.Infrastructure.Http

Anti-Corruption Layer for synchronous HTTP calls between services.

Install

dotnet add package Koto.Infrastructure.Http

What's included

TypePurpose
ServiceHttpClientAbstract base for typed HTTP clients; maps HTTP errors to Result<T>
ICorrelationIdAccessorInterface for providing the current correlation ID
CorrelationIdHandlerDelegating handler that propagates X-Correlation-ID
AddServiceHttpClient<TInterface, TImplementation>()Registers with standard resilience (retry + circuit breaker + timeout)

Usage

1 — Define the application interface (no HTTP here)

// Application layer
public interface IPaymentService
{
    Task<Result<PaymentId>> ChargeAsync(Money amount, CancellationToken ct);
}

2 — Implement with the HTTP client

// Infrastructure layer
public class PaymentServiceHttpClient : ServiceHttpClient, IPaymentService
{
    public PaymentServiceHttpClient(HttpClient http) : base(http) { }

    public async Task<Result<PaymentId>> ChargeAsync(Money amount, CancellationToken ct)
    {
        var response = await Http.PostAsJsonAsync("/charges",
            new { Amount = amount.Amount, Currency = amount.Currency }, ct);
        return await ReadResultAsync<PaymentId>(response, ct);
    }
}

3 — Register

// Implement ICorrelationIdAccessor (typically wraps IHttpContextAccessor):
services.AddScoped<ICorrelationIdAccessor, HttpContextCorrelationIdAccessor>();

services.AddServiceHttpClient<IPaymentService, PaymentServiceHttpClient>(
    name: "payment-service",
    baseUrl: config["Services:Payment:BaseUrl"]!);

Standard resilience pipeline is applied automatically (3 retries with exponential back-off, circuit breaker, 30 s timeout).

Error mapping

HTTP statusError.Code
404general.not-found
409general.conflict
422general.validation
5xxgeneral.unexpected

Override MapErrorResponse to add service-specific error codes.