diff --git a/CHANGELOG.md b/CHANGELOG.md index 495ff05..8d4e898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Fixed a bug where the client would fail on 301/302 responses with no location headers. [#272](https://github.com/microsoft/kiota-dotnet/issues/272) + ## [1.16.0] - 2024-12-13 ### Added diff --git a/src/http/httpClient/HttpClientRequestAdapter.cs b/src/http/httpClient/HttpClientRequestAdapter.cs index 3e6f5de..00c403e 100644 --- a/src/http/httpClient/HttpClientRequestAdapter.cs +++ b/src/http/httpClient/HttpClientRequestAdapter.cs @@ -424,7 +424,7 @@ private static bool shouldReturnNull(HttpResponseMessage response) private async Task ThrowIfFailedResponseAsync(HttpResponseMessage response, Dictionary>? errorMapping, Activity? activityForAttributes, CancellationToken cancellationToken) { using var span = activitySource?.StartActivity(nameof(ThrowIfFailedResponseAsync)); - if(response.IsSuccessStatusCode) return; + if(response.IsSuccessStatusCode || response.StatusCode is HttpStatusCode.Moved or HttpStatusCode.MovedPermanently or HttpStatusCode.Found or HttpStatusCode.Redirect) return; activityForAttributes?.SetStatus(ActivityStatusCode.Error, "received_error_response"); diff --git a/tests/http/httpClient/RequestAdapterTests.cs b/tests/http/httpClient/RequestAdapterTests.cs index 6478d14..838fa31 100644 --- a/tests/http/httpClient/RequestAdapterTests.cs +++ b/tests/http/httpClient/RequestAdapterTests.cs @@ -21,12 +21,12 @@ namespace Microsoft.Kiota.Http.HttpClientLibrary.Tests public class HttpClientRequestAdapterTests { private readonly IAuthenticationProvider _authenticationProvider; - private readonly HttpClientRequestAdapter requestAdapter; + private readonly HttpClientRequestAdapter _requestAdapter; public HttpClientRequestAdapterTests() { _authenticationProvider = new Mock().Object; - requestAdapter = new HttpClientRequestAdapter(new AnonymousAuthenticationProvider()); + _requestAdapter = new HttpClientRequestAdapter(new AnonymousAuthenticationProvider()); } [Fact] @@ -82,7 +82,7 @@ public void EnablesBackingStore() public async Task GetRequestMessageFromRequestInformationWithBaseUrlTemplate() { // Arrange - requestAdapter.BaseUrl = "http://localhost"; + _requestAdapter.BaseUrl = "http://localhost"; var requestInfo = new RequestInformation { HttpMethod = Method.GET, @@ -90,7 +90,7 @@ public async Task GetRequestMessageFromRequestInformationWithBaseUrlTemplate() }; // Act - var requestMessage = await requestAdapter.ConvertToNativeRequestAsync(requestInfo); + var requestMessage = await _requestAdapter.ConvertToNativeRequestAsync(requestInfo); // Assert Assert.NotNull(requestMessage); @@ -113,10 +113,10 @@ public async Task GetRequestMessageFromRequestInformationUsesBaseUrlFromAdapter( }; // Change the baseUrl of the adapter - requestAdapter.BaseUrl = "http://localhost"; + _requestAdapter.BaseUrl = "http://localhost"; // Act - var requestMessage = await requestAdapter.ConvertToNativeRequestAsync(requestInfo); + var requestMessage = await _requestAdapter.ConvertToNativeRequestAsync(requestInfo); // Assert Assert.NotNull(requestMessage); @@ -140,7 +140,7 @@ public async Task GetRequestMessageFromRequestInformationSetsQueryParametersCorr requestInfo.QueryParameters.Add(queryParam, queryParamObject!); // Act - var requestMessage = await requestAdapter.ConvertToNativeRequestAsync(requestInfo); + var requestMessage = await _requestAdapter.ConvertToNativeRequestAsync(requestInfo); // Assert Assert.NotNull(requestMessage); @@ -162,7 +162,7 @@ public async Task GetRequestMessageFromRequestInformationSetsContentHeaders() requestInfo.SetStreamContent(new MemoryStream(Encoding.UTF8.GetBytes("contents")), "application/octet-stream"); // Act - var requestMessage = await requestAdapter.ConvertToNativeRequestAsync(requestInfo); + var requestMessage = await _requestAdapter.ConvertToNativeRequestAsync(requestInfo); // Assert Assert.NotNull(requestMessage); @@ -207,6 +207,31 @@ public async Task SendMethodDoesNotThrowWithoutUrlTemplate() Assert.Equal(4, response.Length); } + [InlineData(HttpStatusCode.Redirect)] + [InlineData(HttpStatusCode.MovedPermanently)] + [Theory] + public async Task SendMethodDoesNotThrowOn3XXWithNoLocationAsync(HttpStatusCode httpStatusCode) + { + var mockHandler = new Mock(); + var client = new HttpClient(mockHandler.Object); + mockHandler.Protected() + .Setup>("SendAsync", ItExpr.IsAny(), ItExpr.IsAny()) + .ReturnsAsync(new HttpResponseMessage + { + StatusCode = httpStatusCode + }); + var adapter = new HttpClientRequestAdapter(_authenticationProvider, httpClient: client); + var requestInfo = new RequestInformation + { + HttpMethod = Method.GET, + URI = new Uri("https://example.com") + }; + + var response = await adapter.SendAsync(requestInfo, MockEntity.Factory); + + Assert.Null(response); + } + [InlineData(HttpStatusCode.OK)] [InlineData(HttpStatusCode.Created)] [InlineData(HttpStatusCode.Accepted)]