Skip to content

Commit

Permalink
Merge pull request #857 from microsoftgraph/andrueastman/compressionA…
Browse files Browse the repository at this point in the history
…lignment

fix: automatic decompression of response content
  • Loading branch information
andrueastman authored Jul 24, 2024
2 parents 441c3af + a501198 commit fa1fb95
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 51 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project does adheres to [Semantic Versioning](https://semver.org/spec/v

## [Unreleased]

## [3.1.14] - 2024-07-23

### Changed

- Obsoletes custom decompression handler in favor of native client capabilities at https://github.com/microsoft/kiota-dotnet/pull/303

## [3.1.12] - 2024-07-03

### Changed
Expand Down
20 changes: 10 additions & 10 deletions src/Microsoft.Graph.Core/Microsoft.Graph.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<AssemblyOriginatorKeyFile>35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<!-- x-release-please-start-version -->
<VersionPrefix>3.1.13</VersionPrefix>
<VersionPrefix>3.1.14</VersionPrefix>
<!-- x-release-please-end -->
<!-- VersionPrefix minor version should not be set when the change comes from the generator. It will be updated automatically. -->
<!-- VersionPrefix minor version must be manually set when making manual changes to code. -->
Expand All @@ -38,7 +38,7 @@
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<PackageReadmeFile>README.md</PackageReadmeFile>
<NoWarn>NU5048;NETSDK1202</NoWarn>
<IsTrimmable>true</IsTrimmable>
<IsTrimmable Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)','net5.0'))">true</IsTrimmable>
</PropertyGroup>
<!-- https://github.com/clairernovotny/DeterministicBuilds#deterministic-builds -->
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
Expand All @@ -62,15 +62,15 @@
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="7.6.2" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.0.1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.Kiota.Abstractions" Version="[1.9.6, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Authentication.Azure" Version="[1.1.7, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Serialization.Json" Version="[1.3.3, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Serialization.Text" Version="[1.2.2, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Serialization.Form" Version="[1.2.5, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="[1.4.3, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Serialization.Multipart" Version="[1.1.5, 2.0.0)" />
<PackageReference Include="Microsoft.Kiota.Abstractions" Version="1.9.11" />
<PackageReference Include="Microsoft.Kiota.Authentication.Azure" Version="1.9.11" />
<PackageReference Include="Microsoft.Kiota.Serialization.Json" Version="1.9.11" />
<PackageReference Include="Microsoft.Kiota.Serialization.Text" Version="1.9.11" />
<PackageReference Include="Microsoft.Kiota.Serialization.Form" Version="1.9.11" />
<PackageReference Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="1.9.11" />
<PackageReference Include="Microsoft.Kiota.Serialization.Multipart" Version="1.9.11" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' ">
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="[6.0,9.0)" />
Expand Down
43 changes: 14 additions & 29 deletions src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,6 @@ public static IList<DelegatingHandler> CreateDefaultHandlers(GraphClientOptions
var handlers = KiotaClientFactory.CreateDefaultHandlers();
handlers.Add(new GraphTelemetryHandler(graphClientOptions));// add the telemetry handler last.

// TODO remove this once https://github.com/microsoft/kiota/issues/598 is closed.
handlers.Insert(0, new CompressionHandler());

return handlers;
}

Expand Down Expand Up @@ -173,20 +170,6 @@ internal static (HttpMessageHandler Pipeline, FeatureFlag FeatureFlags) CreatePi
throw new ArgumentNullException(nameof(handlers), "DelegatingHandler array contains null item.");
}

#if IOS || MACOS || MACCATALYST
#if IOS || MACCATALYST
// Skip CompressionHandler since NSUrlSessionHandler automatically handles decompression on iOS and macOS and it can't be turned off.
// See issue https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/481 for more details.
if (finalHandler.GetType().Equals(typeof(NSUrlSessionHandler)) && handler.GetType().Equals(typeof(CompressionHandler)))
#elif MACOS
if (finalHandler.GetType().Equals(typeof(Foundation.NSUrlSessionHandler)) && handler.GetType().Equals(typeof(CompressionHandler)))
#endif
{
// Skip chaining of CompressionHandler.
continue;
}
#endif

// Check for duplicate handler by type.
if (!existingHandlerTypes.Add(handler.GetType()))
{
Expand Down Expand Up @@ -220,17 +203,17 @@ internal static HttpMessageHandler GetNativePlatformHttpHandler(IWebProxy proxy
#elif MACOS
return new Foundation.NSUrlSessionHandler { AllowAutoRedirect = false };
#elif ANDROID
return new Xamarin.Android.Net.AndroidMessageHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None };
return new Xamarin.Android.Net.AndroidMessageHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.All };
#elif NETFRAMEWORK
// If custom proxy is passed, the WindowsProxyUsePolicy will need updating
// https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs#L575
var proxyPolicy = proxy != null ? WindowsProxyUsePolicy.UseCustomProxy : WindowsProxyUsePolicy.UseWinHttpProxy;
return new WinHttpHandler { Proxy = proxy, AutomaticDecompression = DecompressionMethods.None , WindowsProxyUsePolicy = proxyPolicy, SendTimeout = Timeout.InfiniteTimeSpan, ReceiveDataTimeout = Timeout.InfiniteTimeSpan, ReceiveHeadersTimeout = Timeout.InfiniteTimeSpan };
return new WinHttpHandler { Proxy = proxy, AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate , WindowsProxyUsePolicy = proxyPolicy, SendTimeout = Timeout.InfiniteTimeSpan, ReceiveDataTimeout = Timeout.InfiniteTimeSpan, ReceiveHeadersTimeout = Timeout.InfiniteTimeSpan };
#elif NET6_0_OR_GREATER
//use resilient configs when we can https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0#alternatives-to-ihttpclientfactory-1
return new SocketsHttpHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None, PooledConnectionLifetime = TimeSpan.FromMinutes(1)};
return new SocketsHttpHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.All, PooledConnectionLifetime = TimeSpan.FromMinutes(1)};
#else
return new HttpClientHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None };
return new HttpClientHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
#endif
}

Expand All @@ -241,14 +224,16 @@ internal static HttpMessageHandler GetNativePlatformHttpHandler(IWebProxy proxy
/// <returns>Delegating handler feature flag.</returns>
private static FeatureFlag GetHandlerFeatureFlag(DelegatingHandler delegatingHandler)
{
if (delegatingHandler is CompressionHandler)
return FeatureFlag.CompressionHandler;
else if (delegatingHandler is RetryHandler)
return FeatureFlag.RetryHandler;
else if (delegatingHandler is RedirectHandler)
return FeatureFlag.RedirectHandler;
else
return FeatureFlag.None;
return delegatingHandler switch
{
// Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
CompressionHandler => FeatureFlag.CompressionHandler,
#pragma warning restore CS0618 // Type or member is obsolete
RetryHandler => FeatureFlag.RetryHandler,
RedirectHandler => FeatureFlag.RedirectHandler,
_ => FeatureFlag.None
};
}

private static Uri DetermineBaseAddress(string nationalCloud, string version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ public void Should_CreatePipeline_Without_CompressionHandler()
[Fact]
public void Should_CreatePipeline_Without_HttpMessageHandlerInput()
{
using CompressionHandler compressionHandler = (CompressionHandler)GraphClientFactory.CreatePipeline(handlers, new MockRedirectHandler());
using UriReplacementHandler<UriReplacementHandlerOption> uriReplacementHandler = (UriReplacementHandler<UriReplacementHandlerOption>)compressionHandler.InnerHandler;
using UriReplacementHandler<UriReplacementHandlerOption> uriReplacementHandler = (UriReplacementHandler<UriReplacementHandlerOption>)GraphClientFactory.CreatePipeline(handlers, new MockRedirectHandler());
using RetryHandler retryHandler = (RetryHandler)uriReplacementHandler.InnerHandler;
using RedirectHandler redirectHandler = (RedirectHandler)retryHandler.InnerHandler;
using ParametersNameDecodingHandler odataQueryHandler = (ParametersNameDecodingHandler)redirectHandler.InnerHandler;
Expand All @@ -83,14 +82,12 @@ public void Should_CreatePipeline_Without_HttpMessageHandlerInput()
Assert.NotNull(userAgentHandler);
Assert.NotNull(headersInspectionHandler);
Assert.NotNull(odataQueryHandler);
Assert.NotNull(compressionHandler);
Assert.NotNull(retryHandler);
Assert.NotNull(redirectHandler);
Assert.NotNull(innerMost);
Assert.IsType<GraphTelemetryHandler>(telemetryHandler);
Assert.IsType<ParametersNameDecodingHandler>(odataQueryHandler);
Assert.IsType<HeadersInspectionHandler>(headersInspectionHandler);
Assert.IsType<CompressionHandler>(compressionHandler);
Assert.IsType<UserAgentHandler>(userAgentHandler);
Assert.IsType<RetryHandler>(retryHandler);
Assert.IsType<RedirectHandler>(redirectHandler);
Expand All @@ -101,8 +98,7 @@ public void Should_CreatePipeline_Without_HttpMessageHandlerInput()
[Fact]
public void CreatePipelineWithHttpMessageHandlerInput()
{
using CompressionHandler compressionHandler = (CompressionHandler)GraphClientFactory.CreatePipeline(handlers, new MockRedirectHandler());
using UriReplacementHandler<UriReplacementHandlerOption> uriReplacementHandler = (UriReplacementHandler<UriReplacementHandlerOption>)compressionHandler.InnerHandler;
using UriReplacementHandler<UriReplacementHandlerOption> uriReplacementHandler = (UriReplacementHandler<UriReplacementHandlerOption>)GraphClientFactory.CreatePipeline(handlers, new MockRedirectHandler());
using RetryHandler retryHandler = (RetryHandler)uriReplacementHandler.InnerHandler;
using RedirectHandler redirectHandler = (RedirectHandler)retryHandler.InnerHandler;
using ParametersNameDecodingHandler odataQueryHandler = (ParametersNameDecodingHandler)redirectHandler.InnerHandler;
Expand All @@ -115,14 +111,12 @@ public void CreatePipelineWithHttpMessageHandlerInput()
Assert.NotNull(userAgentHandler);
Assert.NotNull(headersInspectionHandler);
Assert.NotNull(odataQueryHandler);
Assert.NotNull(compressionHandler);
Assert.NotNull(retryHandler);
Assert.NotNull(redirectHandler);
Assert.NotNull(innerMost);
Assert.IsType<GraphTelemetryHandler>(telemetryHandler);
Assert.IsType<ParametersNameDecodingHandler>(odataQueryHandler);
Assert.IsType<HeadersInspectionHandler>(headersInspectionHandler);
Assert.IsType<CompressionHandler>(compressionHandler);
Assert.IsType<RetryHandler>(retryHandler);
Assert.IsType<UserAgentHandler>(userAgentHandler);
Assert.IsType<RedirectHandler>(redirectHandler);
Expand All @@ -143,11 +137,11 @@ public void CreatePipelineWithoutPipeline()
public void CreatePipeline_Should_Throw_Exception_With_Duplicate_Handlers()
{
var handlers = GraphClientFactory.CreateDefaultHandlers();
handlers.Add(new CompressionHandler());
handlers.Add(new GraphTelemetryHandler());

ArgumentException exception = Assert.Throws<ArgumentException>(() => GraphClientFactory.CreatePipeline(handlers));

Assert.Contains($"{typeof(CompressionHandler)} has a duplicate handler.", exception.Message);
Assert.Contains($"{typeof(GraphTelemetryHandler)} has a duplicate handler.", exception.Message);
}

[Fact]
Expand Down Expand Up @@ -281,7 +275,7 @@ public void CreateClient_WithInnerHandlerReference()
[Fact]
public void CreatePipelineWithFeatureFlags_Should_Set_FeatureFlag_For_Default_Handlers()
{
FeatureFlag expectedFlag = FeatureFlag.CompressionHandler | FeatureFlag.RetryHandler | FeatureFlag.RedirectHandler;
FeatureFlag expectedFlag = FeatureFlag.RetryHandler | FeatureFlag.RedirectHandler;
string expectedFlagHeaderValue = Enum.Format(typeof(FeatureFlag), expectedFlag, "x");
var handlers = GraphClientFactory.CreateDefaultHandlers();
var pipelineWithHandlers = GraphClientFactory.CreatePipelineWithFeatureFlags(handlers);
Expand All @@ -293,7 +287,7 @@ public void CreatePipelineWithFeatureFlags_Should_Set_FeatureFlag_For_Default_Ha
[Fact]
public void CreatePipelineWithFeatureFlags_Should_Set_FeatureFlag_For_Speficied_Handlers()
{
FeatureFlag expectedFlag = FeatureFlag.CompressionHandler | FeatureFlag.RetryHandler;
FeatureFlag expectedFlag = FeatureFlag.RetryHandler;
var handlers = GraphClientFactory.CreateDefaultHandlers();
//Exclude the redirect handler for this test
handlers = handlers.Where(handler => !handler.GetType().Equals(typeof(RedirectHandler))).ToList();
Expand Down

0 comments on commit fa1fb95

Please sign in to comment.