From 879ad2add9e1e85655f7cffc33c5f115f5c7754d Mon Sep 17 00:00:00 2001 From: Iliar Turdushev Date: Wed, 16 Jul 2025 18:22:55 +0200 Subject: [PATCH] Fixes #6548 Adds an attempt to retrieve the request message from the resilience context in addition to retrieving the request from the response --- .../Polly/HttpRetryStrategyOptionsExtensions.cs | 8 +++++--- .../HttpRetryStrategyOptionsExtensionsTests.cs | 16 +++++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptionsExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptionsExtensions.cs index 85168988c7b..becd53e1240 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptionsExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Polly/HttpRetryStrategyOptionsExtensions.cs @@ -8,6 +8,7 @@ using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Polly; +using Polly.Retry; namespace Microsoft.Extensions.Http.Resilience; @@ -52,9 +53,7 @@ public static void DisableFor(this HttpRetryStrategyOptions options, params Http { var result = await shouldHandle(args).ConfigureAwait(args.Context.ContinueOnCapturedContext); - if (result && - args.Outcome.Result is HttpResponseMessage response && - response.RequestMessage is HttpRequestMessage request) + if (result && GetRequestMessage(args) is HttpRequestMessage request) { return !methods.Contains(request.Method); } @@ -62,5 +61,8 @@ args.Outcome.Result is HttpResponseMessage response && return result; }; } + + private static HttpRequestMessage? GetRequestMessage(RetryPredicateArguments args) => + args.Outcome.Result?.RequestMessage ?? args.Context.GetRequestMessage(); } diff --git a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Polly/HttpRetryStrategyOptionsExtensionsTests.cs b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Polly/HttpRetryStrategyOptionsExtensionsTests.cs index 4d43c020d1f..996731b08bf 100644 --- a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Polly/HttpRetryStrategyOptionsExtensionsTests.cs +++ b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Polly/HttpRetryStrategyOptionsExtensionsTests.cs @@ -65,12 +65,16 @@ public async Task DisableFor_RespectsOriginalShouldHandlePredicate() } [Fact] - public async Task DisableFor_ResponseMessageIsNull_DoesNotDisableRetries() + public async Task DisableFor_ResponseMessageIsNull_RetrievesRequestMessageFromContext() { var options = new HttpRetryStrategyOptions { ShouldHandle = _ => PredicateResult.True() }; options.DisableFor(HttpMethod.Post); - Assert.True(await options.ShouldHandle(CreatePredicateArguments(null))); + using var request = new HttpRequestMessage { Method = HttpMethod.Post }; + var context = ResilienceContextPool.Shared.Get(); + context.SetRequestMessage(request); + + Assert.False(await options.ShouldHandle(CreatePredicateArguments(null, context))); } [Fact] @@ -80,8 +84,10 @@ public async Task DisableFor_RequestMessageIsNull_DoesNotDisableRetries() options.DisableFor(HttpMethod.Post); using var response = new HttpResponseMessage { RequestMessage = null }; + var context = ResilienceContextPool.Shared.Get(); + context.SetRequestMessage(null); - Assert.True(await options.ShouldHandle(CreatePredicateArguments(response))); + Assert.True(await options.ShouldHandle(CreatePredicateArguments(response, context))); } [Theory] @@ -105,10 +111,10 @@ public async Task DisableForUnsafeHttpMethods_PositiveScenario(string httpMethod Assert.Equal(shouldHandle, await options.ShouldHandle(CreatePredicateArguments(response))); } - private static RetryPredicateArguments CreatePredicateArguments(HttpResponseMessage? response) + private static RetryPredicateArguments CreatePredicateArguments(HttpResponseMessage? response, ResilienceContext? context = null) { return new RetryPredicateArguments( - ResilienceContextPool.Shared.Get(), + context ?? ResilienceContextPool.Shared.Get(), Outcome.FromResult(response), attemptNumber: 1); }