diff --git a/SuccessfulCodeTools.Tests/LowLevelHttpClientTests.cs b/SuccessfulCodeTools.Tests/LowLevelHttpClientTests.cs index af97a35..72387c1 100644 --- a/SuccessfulCodeTools.Tests/LowLevelHttpClientTests.cs +++ b/SuccessfulCodeTools.Tests/LowLevelHttpClientTests.cs @@ -12,14 +12,22 @@ namespace SuccessfulCodeTools.Tests public class LowLevelHttpClientTests { [Fact] - public void CheckLowLevelHttpClientConcurrency() + public void CheckLowLevelHttpClient() { //Arrange - Parallel.ForEach(Enumerable.Range(1, 20), (e) => - { - var client = new CustomHttpClient(32455); - client.SendAsync(new CustomHttpRequestMessage(HttpMethod.Get, "http://www.mocky.io/v2/5e546e473100004900eb31a5")).GetAwaiter().GetResult(); - }); + + var message = new CustomHttpRequestMessage(HttpMethod.Get, "https://www.britishhorseracing.com:443/feeds/v3/fixtures?page=1&per_page=100&order=desc&year=2019&month=2&resultAvailable=True"); + + message.Headers.Add("Accept", "application/json, text/plain, */*"); + message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"); + //message.Headers.TryAddWithoutValidation("Authorization", CurrentToken); + message.Headers.Add("Authorization", "ZGNlNDYxZjdkOGFlM2RlYjE5YmQxZjYyOGM5ZmM3MTg="); + message.Headers.Add("Accept", "application/json"); + message.Headers.Add("accept-encoding", "gzip, deflate"); + message.Headers.Add("Accept-Language", $"en-US,en;q=0.9;id={Guid.NewGuid()}"); + message.Headers.Add("Cookie", "D_ZID=3F37C446-48FB-3F85-B8D2-66FC90A17473; D_ZUID=27B27203-7708-3F5E-8C01-86A8BF3A21DD; D_HID=BC00CAA4-06EE-39E0-8579-A00DCFA20171; D_SID=188.172.158.138:JT/OEx87nl5ScspTQk38UsDfuIz94DbCf5CYsIC7WpU; bha-ie-test=true; __utmc=36595059; __utmz=36595059.1586780062.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); D_IID=A18DB74E-9ABD-33E1-BF94-96209AF6178E; D_UID=9CDC96FD-4EFE-308E-BC28-2F105AC0B01B; bha_token=%7B%22token%22%3A%22NmZjNDgzNTI0YmFlYzM5MmJkN2U4N2E2MTg2YjVlMWY%3D%22%2C%22timestamp%22%3A1586811155132%7D; __utma=36595059.39554265.1586780062.1586811153.1586848611.7; __utmt=1; __utmb=36595059.1.10.1586848611"); + var client = new CustomHttpClient(); + var response = client.SendAsync(message).Result; //Act //Assert } diff --git a/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpClient.cs b/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpClient.cs index a5cdba1..d4d9c63 100644 --- a/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpClient.cs +++ b/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpClient.cs @@ -1,14 +1,8 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; +using System.IO; using System.Linq; using System.Net; -using System.Net.Http; using System.Net.Sockets; using System.Text; -using System.Threading; using System.Threading.Tasks; namespace SuccessfulCodeTools.LowLevelHttpClient @@ -24,7 +18,6 @@ namespace SuccessfulCodeTools.LowLevelHttpClient public async Task SendAsync(CustomHttpRequestMessage message, int? outgoingPort = null) { - var defaultHeaders = DefaultHeaders.Where(e => !message.Headers.Contains(e)).ToArray(); message.Headers.AddRange(defaultHeaders); diff --git a/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpResponseMessage.cs b/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpResponseMessage.cs index 7e869c0..2e35c5e 100644 --- a/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpResponseMessage.cs +++ b/SuccessfulCodeTools/LowLevelHttpClient/CustomHttpResponseMessage.cs @@ -28,7 +28,7 @@ namespace SuccessfulCodeTools.LowLevelHttpClient var statusHeader = splitHeaders[0].Split(' '); Protocol = statusHeader[0]; - if(statusHeader[1][0] == '2') + if (statusHeader[1][0] == '2') { IsSuccessStatusCode = true; } @@ -43,25 +43,51 @@ namespace SuccessfulCodeTools.LowLevelHttpClient .ToArray(); + var chunkIndexes = new List>(); + var carriageReturnBytes = Encoding.ASCII.GetBytes("\r\n"); if (Headers.Any(e => e.Key.Equals("Transfer-Encoding", StringComparison.InvariantCultureIgnoreCase) && e.Value.Equals("chunked", StringComparison.InvariantCultureIgnoreCase))) { - index = BinaryMatch(data, Encoding.ASCII.GetBytes("\r\n"), index) + 2; + var nextIndex = index; + while (nextIndex != -1) + { + var lengthEnd = BinaryMatch(data, carriageReturnBytes, nextIndex); + if (lengthEnd == -1) + break; + + var lengthText = Encoding.ASCII.GetString(data, nextIndex, lengthEnd - nextIndex); + var length = int.Parse(lengthText, System.Globalization.NumberStyles.HexNumber); + if (length == 0) + break; + + chunkIndexes.Add(new KeyValuePair(lengthEnd + 2, length)); + nextIndex = BinaryMatch(data, carriageReturnBytes, lengthEnd + 2) + 2; + } } - memory.Position = index; + if (chunkIndexes.Count > 0) + memory.Position = chunkIndexes[0].Key; + if (!Headers.Where(e => e.Key == "Content-Encoding" && e.Value.StartsWith("gzip")).Any()) { Content = Encoding.UTF8.GetString(data, index, data.Length - index); return; } - - using (var decompressionStream = new GZipStream(memory, CompressionMode.Decompress)) - using (var decompressedMemory = new MemoryStream()) + using (var stream = new MemoryStream()) { - decompressionStream.CopyTo(decompressedMemory); - decompressedMemory.Position = 0; - Content = Encoding.UTF8.GetString(decompressedMemory.ToArray()); + + foreach (var chunk in chunkIndexes) + { + var compressedBytes = data.Skip(chunk.Key).Take(chunk.Value).ToArray(); + stream.Write(compressedBytes, 0, compressedBytes.Length); + } + stream.Position = 0; + using (var decompressionStream = new GZipStream(stream, CompressionMode.Decompress)) + using (var decompressedMemory = new MemoryStream()) + { + decompressionStream.CopyTo(decompressedMemory); + Content += Encoding.UTF8.GetString(decompressedMemory.ToArray()); + } } }