From 6355dd9fc5b26ef01859a33f863acfb61e5e8242 Mon Sep 17 00:00:00 2001 From: Leefrost Date: Sun, 26 Mar 2023 20:57:50 +0300 Subject: [PATCH 1/2] Added headers caching --- src/HttpClient.Cache/CacheData.cs | 12 ++++++++- .../Utils/HttpResponseMessageExtensions.cs | 26 ++++++++++++++----- .../CacheDataExtensionsTests.cs | 8 ++++-- .../InMemory/MemoryCacheExtensionsTests.cs | 16 +++++++++--- .../HttpResponseMessageExtensionsTests.cs | 4 ++- 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/HttpClient.Cache/CacheData.cs b/src/HttpClient.Cache/CacheData.cs index 137853c..42cf218 100644 --- a/src/HttpClient.Cache/CacheData.cs +++ b/src/HttpClient.Cache/CacheData.cs @@ -2,11 +2,21 @@ public class CacheData { - public CacheData(byte[] data, HttpResponseMessage response) + public CacheData( + byte[] data, + Dictionary> headers, + Dictionary> contentHeaders, + HttpResponseMessage response) { Data = data; Response = response; + Headers = headers; + ContentHeaders = contentHeaders; } + + public Dictionary> Headers { get; } + + public Dictionary> ContentHeaders { get; } public byte[] Data { get; } diff --git a/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs b/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs index 4045fa8..92a1688 100644 --- a/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs +++ b/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs @@ -5,14 +5,20 @@ public static class HttpResponseMessageExtensions public static async Task ToCacheDataAsync(this HttpResponseMessage response) { var data = await response.Content.ReadAsByteArrayAsync(); - var copy = new HttpResponseMessage + var copiedResponse = new HttpResponseMessage { ReasonPhrase = response.ReasonPhrase, StatusCode = response.StatusCode, Version = response.Version }; + + var headers = response.Headers + .Where(headers => headers.Value.Any()) + .ToDictionary(header => header.Key, header => header.Value); + + var contentHeaders = response.Content.Headers + .Where(contentHeader => contentHeader.Value.Any()) + .ToDictionary(header => header.Key, header => header.Value); - //TODO: headers are important. Will be added later; - - var entry = new CacheData(data, copy); + var entry = new CacheData(data, headers, contentHeaders, copiedResponse); return entry; } @@ -22,8 +28,16 @@ public static HttpResponseMessage RestoreResponseFromCache(this HttpRequestMessa response.Content = new ByteArrayContent(cacheData.Data); response.RequestMessage = request; - //TODO: headers are important. Will be added later; - + foreach (var kvp in cacheData.Headers) + { + response.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value); + } + + foreach (var kvp in cacheData.ContentHeaders) + { + response.Content.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value); + } + return response; } } \ No newline at end of file diff --git a/tests/HttpClient.Cache.Tests/CacheDataExtensionsTests.cs b/tests/HttpClient.Cache.Tests/CacheDataExtensionsTests.cs index 1dd31a2..3bbc3f6 100644 --- a/tests/HttpClient.Cache.Tests/CacheDataExtensionsTests.cs +++ b/tests/HttpClient.Cache.Tests/CacheDataExtensionsTests.cs @@ -14,7 +14,9 @@ public void Pack_CreateABytesFromCacheData_ReturnByteArray() var message = Encoding.UTF8.GetBytes("Here is a message"); var response = new HttpResponseMessage { Content = new ByteArrayContent(message), StatusCode = HttpStatusCode.OK }; - var data = new CacheData(message, response); + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; + var data = new CacheData(message, headers, contentHeaders, response); var packData = data.Pack(); @@ -37,7 +39,9 @@ public void UnPack_CreateCacheDataEn_ReturnByteArray() var message = Encoding.UTF8.GetBytes("Here is a message"); var response = new HttpResponseMessage { Content = new ByteArrayContent(message), StatusCode = HttpStatusCode.OK }; - var cacheData = new CacheData(message, response); + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; + var cacheData = new CacheData(message, headers, contentHeaders, response); var serializeObject = JsonConvert.SerializeObject(cacheData); var bytes = new byte[serializeObject.Length * sizeof(char)]; Buffer.BlockCopy(serializeObject.ToCharArray(), 0, bytes, 0, bytes.Length); diff --git a/tests/HttpClient.Cache.Tests/InMemory/MemoryCacheExtensionsTests.cs b/tests/HttpClient.Cache.Tests/InMemory/MemoryCacheExtensionsTests.cs index a00c503..e351cd0 100644 --- a/tests/HttpClient.Cache.Tests/InMemory/MemoryCacheExtensionsTests.cs +++ b/tests/HttpClient.Cache.Tests/InMemory/MemoryCacheExtensionsTests.cs @@ -12,8 +12,10 @@ public class MemoryCacheExtensionsTests public async Task TryGetAsync_GetCacheItemFromMemoryCacheOut_ReturnTrue() { const string cacheKey = "key"; + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; var memoryCache = new MemoryCache(new MemoryCacheOptions()); - var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), + var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), headers, contentHeaders, new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); using (var entry = memoryCache.CreateEntry(cacheKey)) @@ -35,8 +37,10 @@ public async Task TryGetAsync_GetCacheItemFromMemoryCacheOut_ReturnTrue() public async Task TrySetAsync_SetCacheDataByKeyAndExpRelativeToNow_ReturnTrue() { const string cacheKey = "key"; + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; var memoryCache = new MemoryCache(new MemoryCacheOptions()); - var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), + var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), headers, contentHeaders, new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); var absoluteTimeoutRelativeToNow = TimeSpan.FromDays(1); @@ -49,8 +53,10 @@ public async Task TrySetAsync_SetCacheDataByKeyAndExpRelativeToNow_ReturnTrue() public async Task TrySetAsync_SetCacheDataByKeyAndAbsoluteExp_ReturnTrue() { const string cacheKey = "key"; + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; var memoryCache = new MemoryCache(new MemoryCacheOptions()); - var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), + var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), headers, contentHeaders, new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); var absoluteExpiration = DateTimeOffset.UtcNow.AddDays(1); @@ -63,8 +69,10 @@ public async Task TrySetAsync_SetCacheDataByKeyAndAbsoluteExp_ReturnTrue() public async Task TrySetAsync_SetCacheDataByKeySlidingWindow_ReturnTrue() { const string cacheKey = "key"; + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; var memoryCache = new MemoryCache(new MemoryCacheOptions()); - var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), + var cacheData = new CacheData(Encoding.UTF8.GetBytes("message"), headers, contentHeaders, new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); var slidingExpiration = TimeSpan.FromDays(1); diff --git a/tests/HttpClient.Cache.Tests/Utils/HttpResponseMessageExtensionsTests.cs b/tests/HttpClient.Cache.Tests/Utils/HttpResponseMessageExtensionsTests.cs index 8bc57c5..f0ffe2c 100644 --- a/tests/HttpClient.Cache.Tests/Utils/HttpResponseMessageExtensionsTests.cs +++ b/tests/HttpClient.Cache.Tests/Utils/HttpResponseMessageExtensionsTests.cs @@ -37,7 +37,9 @@ public void RestoreResponseFromCache_RestoreHttpResponse_ReturnHttpResponseMessa StatusCode = HttpStatusCode.Found, Version = Version.Parse("1.0") }; - var cacheData = new CacheData(content, cachedResponse); + var headers = new Dictionary> { { "header", new[] { "header-value" } } }; + var contentHeaders = new Dictionary> { { "contentHeader", new[] { "contentHeader-value" } } }; + var cacheData = new CacheData(content, headers, contentHeaders, cachedResponse); var newRequest = new HttpRequestMessage { Method = HttpMethod.Get }; var restoredResponse = newRequest.RestoreResponseFromCache(cacheData); From 666edc1aa40dc46f0bb8c926d561d79c18adec31 Mon Sep 17 00:00:00 2001 From: Leefrost Date: Mon, 27 Mar 2023 21:07:38 +0300 Subject: [PATCH 2/2] Update accessibility --- src/HttpClient.Cache/HttpClient.Cache.csproj | 4 ++++ src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/HttpClient.Cache/HttpClient.Cache.csproj b/src/HttpClient.Cache/HttpClient.Cache.csproj index 5022b2d..0c4624a 100644 --- a/src/HttpClient.Cache/HttpClient.Cache.csproj +++ b/src/HttpClient.Cache/HttpClient.Cache.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs b/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs index 92a1688..82ba8da 100644 --- a/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs +++ b/src/HttpClient.Cache/Utils/HttpResponseMessageExtensions.cs @@ -1,8 +1,8 @@ namespace HttpClient.Cache.Utils; -public static class HttpResponseMessageExtensions +internal static class HttpResponseMessageExtensions { - public static async Task ToCacheDataAsync(this HttpResponseMessage response) + internal static async Task ToCacheDataAsync(this HttpResponseMessage response) { var data = await response.Content.ReadAsByteArrayAsync(); var copiedResponse = new HttpResponseMessage @@ -22,7 +22,7 @@ public static async Task ToCacheDataAsync(this HttpResponseMessage re return entry; } - public static HttpResponseMessage RestoreResponseFromCache(this HttpRequestMessage request, CacheData cacheData) + internal static HttpResponseMessage RestoreResponseFromCache(this HttpRequestMessage request, CacheData cacheData) { var response = cacheData.Response; response.Content = new ByteArrayContent(cacheData.Data);