Skip to content

Commit

Permalink
API that allows to remove all resilience handlers from the HTTP client (
Browse files Browse the repository at this point in the history
#5801)

* Add API to clear the http client resilience handlers

* Additional tests

* Add experimental attribute to the new API

* Fix formatting

* Add the check for the handler type, formatting

* Formatting

* Additional test to ensure that new API removes only resilience handlers

* Review fixes

* Review fixes
  • Loading branch information
rainsxng authored Jan 21, 2025
1 parent e1c0f17 commit d586dc4
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.ExceptionSummarization;
using Microsoft.Extensions.Http.Resilience;
using Microsoft.Extensions.Http.Resilience.Internal;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
using Polly;
using Polly.Registry;
Expand Down Expand Up @@ -75,6 +77,28 @@ public static IHttpResiliencePipelineBuilder AddResilienceHandler(
return pipelineBuilder;
}

/// <summary>
/// Removes all resilience handlers registered earlier.
/// </summary>
/// <param name="builder">The builder instance.</param>
/// <returns>The value of <paramref name="builder"/>.</returns>
[Experimental(diagnosticId: DiagnosticIds.Experiments.Resilience, UrlFormat = DiagnosticIds.UrlFormat)]
public static IHttpClientBuilder RemoveAllResilienceHandlers(this IHttpClientBuilder builder)
{
_ = Throw.IfNull(builder);
_ = builder.ConfigureAdditionalHttpMessageHandlers(static (handlers, _) =>
{
for (int i = handlers.Count - 1; i >= 0; i--)
{
if (handlers[i] is ResilienceHandler)
{
handlers.RemoveAt(i);
}
}
});
return builder;
}

private static Func<HttpRequestMessage, ResiliencePipeline<HttpResponseMessage>> CreatePipelineSelector(IServiceProvider serviceProvider, string pipelineName)
{
var resilienceProvider = serviceProvider.GetRequiredService<ResiliencePipelineProvider<HttpKey>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
Expand Down Expand Up @@ -286,6 +287,77 @@ public void AddResilienceHandler_AuthorityByCustomSelector_NotValidated()
Assert.NotNull(factory.CreateClient("my-client"));
}

[Fact]
public void RemoveAllResilienceHandlers_ArgumentValidation()
{
var services = new ServiceCollection();
IHttpClientBuilder? builder = null;
Assert.Throws<ArgumentNullException>(() => builder!.RemoveAllResilienceHandlers());
}

[Fact]
public void RemoveAllResilienceHandlers_EnsureHandlersRemoved()
{
var services = new ServiceCollection();

IHttpClientBuilder? builder = services.AddHttpClient("custom");

builder.AddStandardResilienceHandler();

builder.ConfigureAdditionalHttpMessageHandlers((handlers, _) =>
{
Assert.Single(handlers);
});

builder.RemoveAllResilienceHandlers();

builder.ConfigureAdditionalHttpMessageHandlers((handlers, _) =>
{
Assert.Empty(handlers);
});

using ServiceProvider serviceProvider = services.BuildServiceProvider();
serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient("custom");
}

[Fact]
public void RemoveAllResilienceHandlers_AddHandlersAfterRemoval()
{
var services = new ServiceCollection();

IHttpClientBuilder? builder = services.AddHttpClient("custom");
builder.RemoveAllResilienceHandlers().AddStandardResilienceHandler();
builder.ConfigureAdditionalHttpMessageHandlers((handlers, _) =>
{
Assert.Single(handlers);
});

using ServiceProvider serviceProvider = services.BuildServiceProvider();
serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient("custom");
}

[Fact]
public void RemoveAllResilienceHandlers_EnsureOnlyResilienceHandlersRemoved()
{
var services = new ServiceCollection();

IHttpClientBuilder? builder = services.AddHttpClient("custom");

builder.AddHttpMessageHandler(() => new TestHandlerStub(HttpStatusCode.OK));
builder.AddStandardResilienceHandler();

builder.RemoveAllResilienceHandlers();

builder.ConfigureAdditionalHttpMessageHandlers((handlers, _) =>
{
Assert.Single(handlers);
Assert.Equal(typeof(TestHandlerStub), handlers.First().GetType());
});

using ServiceProvider serviceProvider = services.BuildServiceProvider();
serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient("custom");
}

private void ConfigureBuilder(ResiliencePipelineBuilder<HttpResponseMessage> builder) => builder.AddTimeout(TimeSpan.FromSeconds(1));

private class TestMetricsEnricher : MeteringEnricher
Expand Down

0 comments on commit d586dc4

Please sign in to comment.