Support chunked http messages
SuccessfulCode/SuccessfulCodeTools/master This commit looks good

This commit is contained in:
2020-04-14 09:01:21 +01:00
parent cd34a10f74
commit 26d63b3511
3 changed files with 50 additions and 23 deletions
@@ -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
}
@@ -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<CustomHttpResponseMessage> SendAsync(CustomHttpRequestMessage message, int? outgoingPort = null)
{
var defaultHeaders = DefaultHeaders.Where(e => !message.Headers.Contains(e)).ToArray();
message.Headers.AddRange(defaultHeaders);
@@ -43,25 +43,51 @@ namespace SuccessfulCodeTools.LowLevelHttpClient
.ToArray();
var chunkIndexes = new List<KeyValuePair<int, int>>();
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<int, int>(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 stream = new MemoryStream())
{
using (var decompressionStream = new GZipStream(memory, CompressionMode.Decompress))
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);
decompressedMemory.Position = 0;
Content = Encoding.UTF8.GetString(decompressedMemory.ToArray());
Content += Encoding.UTF8.GetString(decompressedMemory.ToArray());
}
}
}