Skip to content
Merged
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 @@ -286,6 +286,56 @@ 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!.AddResilienceHandler("pipeline-name", _ => { }));
Assert.Throws<ArgumentNullException>(() => builder!.AddResilienceHandler("pipeline-name", (_, _) => { }));
}

[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();
services.BuildServiceProvider().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();
services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>().CreateClient("custom");
}

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

private class TestMetricsEnricher : MeteringEnricher
Expand Down