AugusteVN.HttpClient.Delegator 1.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package AugusteVN.HttpClient.Delegator --version 1.0.2
NuGet\Install-Package AugusteVN.HttpClient.Delegator -Version 1.0.2
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AugusteVN.HttpClient.Delegator" Version="1.0.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AugusteVN.HttpClient.Delegator --version 1.0.2
#r "nuget: AugusteVN.HttpClient.Delegator, 1.0.2"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install AugusteVN.HttpClient.Delegator as a Cake Addin
#addin nuget:?package=AugusteVN.HttpClient.Delegator&version=1.0.2

// Install AugusteVN.HttpClient.Delegator as a Cake Tool
#tool nuget:?package=AugusteVN.HttpClient.Delegator&version=1.0.2

Named HttpClient with Delegator

Adds a named HttpClient, a delegator that can add headers to the request, a keyed singleton to share values with the delegator and a resolver for that keyed singleton. The interface of the resolver 'IHttpClientFactory<T>' implements the original 'IHttpClientFactory', hides its methods but uses those under the hood.

It contains what was covered in this video: Authorize HttpClient with Delegating Handler C# .NET

Sandbox, work in progress

builder.Services.AddHttpClient(nameof(TUtils), client => client.BaseAddress = new Uri("https://localhost:3000"))
    .AddDelegator<TUtils>();

builder.Services.AddHttpClient(nameof(TPetService), client => client.BaseAddress = new Uri("https://localhost:3005"))
    .AddDelegator<TPetService>();

builder.Services.AddHttpClientStateResolver<NewsletterSubscribersHttpClient>(nameof(TUtils));

builder.Services.AddScoped<AuthService>();
builder.Services.AddScoped<PetService>();
builder.Services.AddScoped<NewsletterSubscribersHttpClient>();

var app = builder.Build();

app.MapGet("/", (AuthService auth, NewsletterSubscribersHttpClient news, PetService pet) =>
{
    auth.AuthorizeClient("<access-token>");
    auth.PrintLocalState(); // AuthService Local: client name: [TUtils], headers: [[x-news, bar]]
    auth.PrintGlobalState(); // AuthService Global: client names: [TPetService,TUtils], headers: [[x-bar, foo],[Authorization, Bearer <access-token>]]
    
    news.PrintLocalState(); // Newsletter Local: client name: [TUtils], headers: [[x-news, bar]]
    news.PrintGlobalState(); // Newsletter Global: client names: [TPetService,TUtils], headers: [[x-bar, foo],[Authorization, Bearer <access-token>]]

    pet.PrintLocalState(); // PetService Local: client name: [TPetService], headers: [[x-pet-service, foo]]
    pet.PrintGlobalState(); // PetService Global: client names: [TPetService,TUtils], headers: [[x-bar, foo],[Authorization, Bearer <access-token>]]
    Results.Ok();
});

app.Run();

public record TUtils;
public record TPetService;

public class AuthService
{
    private readonly HttpClient _httpClient;
    private readonly IHttpClientFactory<TUtils> _httpState;
    public AuthService(IHttpClientFactory<TUtils> httpState)
    {
        _httpClient = httpState.CreateClient();
        _httpState = httpState;
    }

    public void AuthorizeClient(string? token)
    {
        _httpState.Global.AddHeader("Authorization", $"Bearer {token}");
    }

    public void PrintLocalState()
    {
        Console.WriteLine($"AuthService Local: client name: [{_httpState.Local.ClientName}], headers: [{string.Join(',', _httpState.Local.Headers)}]");
    }

    public void PrintGlobalState()
    {
        Console.WriteLine($"AuthService Global: client names: [{string.Join(',', _httpState.Global.ClientNames)}], headers: [{string.Join(',', _httpState.Global.Headers)}]");
    }
}

public class PetService
{
    private readonly HttpClient _httpClient;
    private readonly IHttpClientFactory<TPetService> _httpState;
    public PetService(IHttpClientFactory<TPetService> httpState)
    {
        _httpClient = httpState.CreateClient();
        _httpState = httpState;
        _httpState.Local.AddHeader("x-pet-service", "foo");
    }

    public void PrintLocalState()
    {
        Console.WriteLine($"PetService Local: client name: [{_httpState.Local.ClientName}], headers: [{string.Join(',', _httpState.Local.Headers)}]");
    }

    public void PrintGlobalState()
    {
        Console.WriteLine($"PetService Global: client names: [{string.Join(',', _httpState.Global.ClientNames)}], headers: [{string.Join(',', _httpState.Global.Headers)}]");
    }
}

public class NewsletterSubscribersHttpClient
{
    private readonly HttpClient _httpClient;
    private readonly IHttpClientFactory<NewsletterSubscribersHttpClient> _httpState;
    public NewsletterSubscribersHttpClient(IHttpClientFactory<NewsletterSubscribersHttpClient> httpState)
    {
        _httpClient = httpState.CreateClient();
        _httpState = httpState;
        _httpState.Local.AddHeader("x-news", "bar");
        _httpState.Global.AddHeader("x-bar", "foo");
    }

    public void PrintLocalState()
    {
        Console.WriteLine($"Newsletter Local: client name: [{_httpState.Local.ClientName}], headers: [{string.Join(',', _httpState.Local.Headers)}]");
    }

    public void PrintGlobalState()
    {
        Console.WriteLine($"Newsletter Global: client names: [{string.Join(',', _httpState.Global.ClientNames)}], headers: [{string.Join(',', _httpState.Global.Headers)}]");
    }
}
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.3 516 11/27/2023
1.0.2 840 11/26/2023

Added local and global state to share headers and override global ones by local ones.