Skip to content

Commit 2fbbbd7

Browse files
author
George
committed
Copy Http Content headers to the destination stream in compression handler.
1 parent b2d9d7c commit 2fbbbd7

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

src/Microsoft.Graph.Core/Requests/Middleware/CompressionHandler.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Microsoft.Graph
99
using System.Threading.Tasks;
1010
using System.Net.Http.Headers;
1111
using System.IO.Compression;
12+
using System.Collections.Generic;
1213

1314
/// <summary>
1415
/// A <see cref="DelegatingHandler"/> implementation that handles compression.
@@ -53,7 +54,13 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
5354
// Decompress response content when Content-Encoding: gzip header is present.
5455
if (ShouldDecompressContent(response))
5556
{
56-
response.Content = new StreamContent(new GZipStream(await response.Content.ReadAsStreamAsync(), CompressionMode.Decompress));
57+
StreamContent streamContent = new StreamContent(new GZipStream(await response.Content.ReadAsStreamAsync(), CompressionMode.Decompress));
58+
// Copy Content Headers to the destination stream content
59+
foreach (var httpContentHeader in response.Content.Headers)
60+
{
61+
streamContent.Headers.TryAddWithoutValidation(httpContentHeader.Key, httpContentHeader.Value);
62+
}
63+
response.Content = streamContent;
5764
}
5865

5966
return response;

tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/Middleware/CompressionHandlerTests.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ namespace Microsoft.Graph.DotnetCore.Core.Test.Requests.Middleware
1212
using System.Threading.Tasks;
1313
using System.Threading;
1414
using System.Net.Http.Headers;
15+
using System.Linq;
16+
using System.Collections.Generic;
17+
using Xunit.Abstractions;
1518

1619
public class CompressionHandlerTests : IDisposable
1720
{
@@ -94,5 +97,54 @@ public async Task CompressionHandler_should_not_decompress_response_without_cont
9497
Assert.Same(httpRequestMessage, compressedResponse.RequestMessage);
9598
Assert.NotEqual(stringToCompress, responseContentString);
9699
}
100+
101+
/// <summary>
102+
/// Compression Handler should keep content headers after decompression
103+
/// </summary>
104+
/// <returns></returns>
105+
[Fact]
106+
public async Task CompressionHandler_should_keep_headers_after_decompression()
107+
{
108+
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.org/foo");
109+
110+
string stringToCompress = "Microsoft Graph";
111+
StringContent stringContent = new StringContent(stringToCompress);
112+
stringContent.Headers.ContentType = new MediaTypeHeaderValue(CoreConstants.MimeTypeNames.Application.Json);
113+
114+
HttpResponseMessage httpResponse = new HttpResponseMessage(HttpStatusCode.OK)
115+
{
116+
Content = new MockCompressedContent(stringContent)
117+
};
118+
httpResponse.Content.Headers.ContentEncoding.Add(CoreConstants.Encoding.GZip);
119+
httpResponse.Headers.CacheControl = new CacheControlHeaderValue { Private = true };
120+
// Examples of Custom Headers returned by Microsoft Graph
121+
httpResponse.Headers.Add(CoreConstants.Headers.ClientRequestId, Guid.NewGuid().ToString());
122+
httpResponse.Headers.Add("request-id", Guid.NewGuid().ToString());
123+
httpResponse.Headers.Add("OData-Version", "4.0");
124+
125+
this.testHttpMessageHandler.SetHttpResponse(httpResponse);
126+
127+
HttpResponseMessage compressedResponse = await this.invoker.SendAsync(httpRequestMessage, new CancellationToken());
128+
string responseContentString = await compressedResponse.Content.ReadAsStringAsync();
129+
130+
// Ensure that headers in the compressedResponse are the same as in the original, expected response.
131+
Assert.NotEmpty(compressedResponse.Content.Headers);
132+
Assert.Equal(httpResponse.Headers, compressedResponse.Headers, new HttpHeaderComparer());
133+
Assert.Equal(httpResponse.Content.Headers, compressedResponse.Content.Headers, new HttpHeaderComparer());
134+
}
135+
136+
internal class HttpHeaderComparer : IEqualityComparer<KeyValuePair<string, IEnumerable<string>>>
137+
{
138+
public bool Equals(KeyValuePair<string, IEnumerable<string>> x, KeyValuePair<string, IEnumerable<string>> y)
139+
{
140+
// For each key, the collection of header values should be equal.
141+
return x.Key == y.Key && x.Value.SequenceEqual(y.Value);
142+
}
143+
144+
public int GetHashCode(KeyValuePair<string, IEnumerable<string>> obj)
145+
{
146+
return obj.Key.GetHashCode();
147+
}
148+
}
97149
}
98150
}

0 commit comments

Comments
 (0)