Skip to content

Latest commit

 

History

History
212 lines (157 loc) · 5.74 KB

File metadata and controls

212 lines (157 loc) · 5.74 KB

Getting Started Guide

Detailed setup guide for Reliable.HttpClient with step-by-step explanations.

🚀 Quick Start: For fastest setup, see README Quick Start

Installation

Choose the packages you need:

Core Resilience Only

dotnet add package Reliable.HttpClient

Includes: Retry policies, circuit breaker, smart error handling

Core + Caching

dotnet add package Reliable.HttpClient
dotnet add package Reliable.HttpClient.Caching

Includes: Everything above + HTTP response caching

Step-by-Step Setup

Step 1: Basic Resilience

// Minimal setup - works out of the box
builder.Services.AddHttpClient<MyApiClient>(c =>
{
    c.BaseAddress = new Uri("https://api.example.com");
})
.AddResilience(); // Zero configuration needed!

What this gives you:

  • Automatic retries (3 attempts with exponential backoff)
  • Circuit breaker (opens after 5 failures)
  • Smart error handling (5xx, timeouts, rate limits)

Step 1.5: Adding Headers

For APIs that require authentication or custom headers:

// Static headers (same for all requests)
builder.Services.AddHttpClient<MyApiClient>(c =>
{
    c.BaseAddress = new Uri("https://api.example.com");
})
.AddResilience(options =>
{
    options.DefaultHeaders["X-API-Key"] = "your-api-key";
    options.DefaultHeaders["Accept"] = "application/json";
});

// Or using fluent builder
builder.Services.AddHttpClient<MyApiClient>(c =>
{
    c.BaseAddress = new Uri("https://api.example.com");
})
.AddResilience(builder => builder
    .WithHeader("X-API-Key", "your-api-key")
    .WithHeader("Accept", "application/json"));

For dynamic headers (like OAuth tokens), see Caching with Custom Headers Documentation.

Step 2: Choose Your Architecture Pattern

Different patterns work better for different scenarios:

Option A: Traditional Generic (Best for 1-2 entity types)

// Add memory cache service first
services.AddMemoryCache();

// Then add caching to your HttpClient
services.AddHttpClient<MyApiClient>(c =>
{
    c.BaseAddress = new Uri("https://api.example.com");
})
.AddResilience()
.AddMemoryCache<MyResponse>(options =>
{
    options.DefaultExpiry = TimeSpan.FromMinutes(5);
});

Option B: Universal Handlers (Best for 5+ entity types)

// Add universal cached client
services.AddHttpClientWithCache(options =>
{
    options.DefaultExpiry = TimeSpan.FromMinutes(5);
});

// Use with any entity type
public class ApiClient(IHttpClientWithCache client)
{
    public async Task<User> GetUserAsync(int id) =>
        await client.GetAsync<User>($"/users/{id}");

    public async Task<Order> GetOrderAsync(int id) =>
        await client.GetAsync<Order>($"/orders/{id}");
    // ... many more entity types without additional registrations
}

Option C: Substitution Pattern (Best for inheritance scenarios)

// Base client using adapter interface
public class BaseApiClient(IHttpClientAdapter client)
{
    protected readonly IHttpClientAdapter Client = client;

    public virtual async Task<T> GetAsync<T>(string endpoint) =>
        await Client.GetAsync<T>(endpoint);
}

// Cached version through inheritance
public class CachedApiClient : BaseApiClient
{
    private readonly IHttpClientWithCache _cachedClient;

    public CachedApiClient(IHttpClientWithCache client) : base(client)
    {
        _cachedClient = client;
    }

    // Override with caching-specific functionality
    public override async Task<T> GetAsync<T>(string endpoint) =>
        await _cachedClient.GetAsync<T>(endpoint, TimeSpan.FromMinutes(5));
}

📖 Need help choosing? See our Choosing Guide for detailed comparison

Key benefits of each approach:

  • Traditional: Maximum type safety and control per entity
  • Universal: Minimal registration overhead, works with any type
  • Substitution: Clean inheritance patterns, easy testing with mocks

Step 3: Custom Configuration (Optional)

Need different settings? Multiple options available:

// Option 1: Simple overrides
.AddResilience(options => options.Retry.MaxRetries = 5)

// Option 2: Fluent builder
.AddResilience(builder => builder.WithRetry(r => r.WithMaxRetries(5)))

// Option 3: Ready-made presets
.AddResilience(HttpClientPresets.SlowExternalApi())

📖 Complete Configuration Guide: See Configuration Reference for all options and presets

Using Your Client

Example: Complete Service

public class WeatherService
{
    private readonly HttpClient _httpClient;

    public WeatherService(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient<WeatherApiClient>();
    }

    public async Task<WeatherData> GetWeatherAsync(string city)
    {
        // This call now has retry, circuit breaker, and caching!
        var response = await _httpClient.GetAsync($"/weather?city={city}");
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<WeatherData>();
    }
}

That's it! Your HTTP client is now production-ready with resilience and caching.

What's Included

  • 3 retry attempts with exponential backoff + jitter
  • Circuit breaker opens after 5 failures for 1 minute
  • Smart error handling for 5xx, timeouts, rate limits
  • Response caching with 5-minute default expiry (if enabled)
  • Configuration validation at startup
  • Zero overhead when not needed

Next Steps