diff --git a/Contentful.AspNetCore/Contentful.AspNetCore.csproj b/Contentful.AspNetCore/Contentful.AspNetCore.csproj
index 995bda4..9fcdc13 100644
--- a/Contentful.AspNetCore/Contentful.AspNetCore.csproj
+++ b/Contentful.AspNetCore/Contentful.AspNetCore.csproj
@@ -3,7 +3,7 @@
Official .NET SDK for the Contentful Content Delivery and Management API for ASP.NET core.
contentful.aspnetcore
en-US
- 8.3.1
+ 8.3.2
netstandard2.0
Contentful
Contentful GmbH.
@@ -13,10 +13,10 @@
https://github.com/contentful/contentful.net
MIT
git
- 8.3.1
- 8.3.1.0
+ 8.3.2
+ 8.3.2.0
https://github.com/contentful/contentful.net
- 8.3.1.0
+ 8.3.2.0
bin\Release\netstandard1.5\Contentful.AspNetCore.xml
@@ -25,7 +25,7 @@
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
-
+
diff --git a/Contentful.Core.Tests/ContentfulClientTests.cs b/Contentful.Core.Tests/ContentfulClientTests.cs
index 4215045..5c48e84 100644
--- a/Contentful.Core.Tests/ContentfulClientTests.cs
+++ b/Contentful.Core.Tests/ContentfulClientTests.cs
@@ -1695,6 +1695,38 @@ public async Task CreateEmbargoedAssetKeyShouldReturnCorrectKey()
Assert.Equal("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjE6MSJ9.eyJleHAiOjE2Mzc2MjM4MDAsInN1YiI6InRlc3RzcGFjZXZhbHVlIiwiYXVkIjoiYWRuIiwianRpIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwiY3RmOnVucHViIjp0cnVlfQ.BHtBHdrInzu3KtGxTJ7FLxGF0WN9HEdJ9C5CeB3hx7g", res.Policy);
}
+ [Fact]
+ public async Task RateLimitWithMultipleRetriesShouldNotThrowObjectDisposedException()
+ {
+ //Arrange
+ _handler = new FakeMessageHandler();
+ var httpClient = new HttpClient(_handler);
+ _client = new ContentfulClient(httpClient, new ContentfulOptions()
+ {
+ DeliveryApiKey = "123",
+ ManagementApiKey = "123",
+ SpaceId = "666",
+ UsePreviewApi = false,
+ MaxNumberOfRateLimitRetries = 3
+ });
+
+ var response = GetResponseFromFile(@"ErrorRateLimit.json");
+ response.StatusCode = (HttpStatusCode)429;
+ response.Headers.Add("X-Contentful-RateLimit-Reset", "1");
+
+ _handler.Response = response;
+ var numberOfTimesCalled = 0;
+ _handler.VerificationBeforeSend = () => { numberOfTimesCalled++; };
+ _handler.VerifyRequest = (HttpRequestMessage msg) => { response.RequestMessage = msg; };
+
+ //Act & Assert
+ // This should not throw ObjectDisposedException
+ var ex = await Assert.ThrowsAsync(async () => await _client.GetEntry("12"));
+
+ Assert.Equal(1, ex.SecondsUntilNextRequest);
+ Assert.Equal(4, numberOfTimesCalled); // 1 initial request + 3 retries
+ }
+
private ContentfulClient GetClientWithEnvironment(string env = "special")
{
var httpClient = new HttpClient(_handler);
diff --git a/Contentful.Core/Contentful.Core.csproj b/Contentful.Core/Contentful.Core.csproj
index 193261c..f909cfb 100644
--- a/Contentful.Core/Contentful.Core.csproj
+++ b/Contentful.Core/Contentful.Core.csproj
@@ -4,7 +4,7 @@
contentful.csharp
contentful.net
en-US
- 8.3.1
+ 8.3.2
netstandard2.0
Contentful
Contentful GmbH.
diff --git a/Contentful.Core/ContentfulClientBase.cs b/Contentful.Core/ContentfulClientBase.cs
index a8b83c8..7381f40 100644
--- a/Contentful.Core/ContentfulClientBase.cs
+++ b/Contentful.Core/ContentfulClientBase.cs
@@ -309,6 +309,9 @@ protected async Task EnsureSuccessfulResult(HttpResponseMes
{
if (!response.IsSuccessStatusCode)
{
+ // Store the original request message to prevent disposal issues during retries
+ var requestMessage = response.RequestMessage;
+
if(response.StatusCode == System.Net.HttpStatusCode.NotModified)
{
return response;
@@ -320,14 +323,15 @@ protected async Task EnsureSuccessfulResult(HttpResponseMes
{
try
{
- await CreateExceptionForFailedRequest(response).ConfigureAwait(false); ;
+ await CreateExceptionForFailedRequest(response).ConfigureAwait(false);
}
catch (ContentfulRateLimitException ex)
{
await Task.Delay(ex.SecondsUntilNextRequest * 1000).ConfigureAwait(false);
}
- using var clonedMessage = await CloneHttpRequest(response.RequestMessage);
+ // Clone from the original request message to avoid disposed message issues
+ using var clonedMessage = await CloneHttpRequest(requestMessage);
response = await _httpClient.SendAsync(clonedMessage, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);