Skip to content

Commit

Permalink
Merge pull request #12 from Ali-YousefiTelori/develop
Browse files Browse the repository at this point in the history
Add support for http listener and improvement performance
  • Loading branch information
Ali-YousefiTelori authored Oct 23, 2023
2 parents 0c42101 + d592fe7 commit af6e28a
Show file tree
Hide file tree
Showing 11 changed files with 722 additions and 330 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
using EasyMicroservices.Laboratory.Constants;
using EasyMicroservices.Laboratory.Engine;
using EasyMicroservices.Laboratory.Engine.Net;
using EasyMicroservices.Laboratory.Engine.Net.Http;
using EasyMicroservices.Laboratory.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace EasyMicroservice.Laboratory.Tests.Engine.Net.Http
namespace EasyMicroservice.Laboratory.Tests.Engine.Net
{
public class HttpHandlerTest : BaseHandler
public abstract class BaseHandlerTest
{

protected abstract BaseHandler GetHandler(ResourceManager resourceManager);
public string GetHttpResponseHeaders(string response)
{
return @$"HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Vary: Accept-Encoding
Date: Mon, 16 Mar 2020 07:48:17 GMT
{response}";
}

string NormalizeOSText(string text)
{
#if (!NET452 && !NET48)
Expand All @@ -30,8 +47,7 @@ public async Task CheckSimpleRequestAndResponse(string request, string response)
response = NormalizeOSText(response);
ResourceManager resourceManager = new ResourceManager();
resourceManager.Append(request, GetHttpResponseHeaders(response));
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();

HttpClient httpClient = new HttpClient();
var data = new StringContent(request);
Expand All @@ -49,8 +65,7 @@ public async Task ConcurrentCheckSimpleRequestAndResponse(string request, string
response = NormalizeOSText(response);
ResourceManager resourceManager = new ResourceManager();
resourceManager.Append(request, GetHttpResponseHeaders(response));
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();

List<Task<bool>> all = new List<Task<bool>>();
for (int i = 0; i < 100; i++)
Expand Down Expand Up @@ -78,8 +93,7 @@ public async Task ConcurrentSingleHttpClientCheckSimpleRequestAndResponse(string
response = NormalizeOSText(response);
ResourceManager resourceManager = new ResourceManager();
resourceManager.Append(request, GetHttpResponseHeaders(response));
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();
HttpClient httpClient = new HttpClient();

List<Task<bool>> all = new List<Task<bool>>();
Expand All @@ -98,14 +112,13 @@ public async Task ConcurrentSingleHttpClientCheckSimpleRequestAndResponse(string
}

[Theory]
[InlineData("Hello Ali \r\n Hi Mahdi", $"POST / HTTP/1.1\r\nHost: localhost:*MyPort*\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 21\r\n\r\nHello Ali \r\n Hi Mahdi")]
[InlineData("Hello Ali \r\n Hi Mahdi", $"POST / HTTP/1.1\r\nContent-Length: 21\r\nContent-Type: text/plain; charset=utf-8\r\nHost: localhost:*MyPort*\r\n\r\nHello Ali \r\n Hi Mahdi")]
public async Task CheckSimpleRequestToGiveMeFullRequestHeaderValue(string request, string response)
{
request = NormalizeOSText(request);
response = NormalizeOSText(response);
ResourceManager resourceManager = new ResourceManager();
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();
response = response.Replace("*MyPort*", port.ToString());
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.ExpectContinue = false;
Expand All @@ -119,14 +132,13 @@ public async Task CheckSimpleRequestToGiveMeFullRequestHeaderValue(string reques
}

[Theory]
[InlineData("Hello Ali \r\n Hi Mahdi", $"POST / HTTP/1.1\r\nHost: localhost:*MyPort*\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 21\r\n\r\nHello Ali \r\n Hi Mahdi")]
[InlineData("Hello Ali \r\n Hi Mahdi", $"POST / HTTP/1.1\r\nContent-Length: 21\r\nContent-Type: text/plain; charset=utf-8\r\nHost: localhost:*MyPort*\r\n\r\nHello Ali \r\n Hi Mahdi")]
public async Task CheckSimpleRequestToGiveMeLastFullRequestHeaderValue(string request, string response)
{
request = NormalizeOSText(request);
response = NormalizeOSText(response);
ResourceManager resourceManager = new ResourceManager();
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();
response = response.Replace("*MyPort*", port.ToString());
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.ExpectContinue = false;
Expand Down Expand Up @@ -172,8 +184,7 @@ public async Task CheckComplex(string request, string response, string simpleRes
response = NormalizeOSText(response);
ResourceManager resourceManager = new ResourceManager();
resourceManager.Append(request, response);
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("x-amz-meta-title", "someTitle");
httpClient.DefaultRequestHeaders.Add("User-Agent", "aws-sdk-dotnet-coreclr/3.7.101.44 aws-sdk-dotnet-core/3.7.103.6 .NET_Core/6.0.11 OS/Microsoft_Windows_10.0.22000 ClientAsync");
Expand Down Expand Up @@ -236,8 +247,7 @@ public async Task CheckScope()
Reza"));
resourceManager.Append(scope);
HttpHandler httpHandler = new HttpHandler(resourceManager);
var port = await httpHandler.Start();
var port = await GetHandler(resourceManager).Start();
var addHeaders = (HttpClient client) =>
{
client.DefaultRequestHeaders.Add("x-amz-meta-title", "someTitle");
Expand Down Expand Up @@ -268,4 +278,4 @@ public async Task CheckScope()
Assert.Equal("Ali", textResponse);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using EasyMicroservice.Laboratory.Tests.Engine.Net;
using EasyMicroservices.Laboratory.Engine;
using EasyMicroservices.Laboratory.Engine.Net;
using EasyMicroservices.Laboratory.Engine.Net.Http;

namespace EasyMicroservices.Laboratory.Tests.Engine.Net
{
public class HttpHandlerTest : BaseHandlerTest
{
protected override BaseHandler GetHandler(ResourceManager resourceManager)
{
return new HttpHandler(resourceManager);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using EasyMicroservice.Laboratory.Tests.Engine.Net;
using EasyMicroservices.Laboratory.Engine;
using EasyMicroservices.Laboratory.Engine.Net;
using EasyMicroservices.Laboratory.Engine.Net.Http;

namespace EasyMicroservices.Laboratory.Tests.Engine.Net
{
public class TcpHandlerTest : BaseHandlerTest
{
protected override BaseHandler GetHandler(ResourceManager resourceManager)
{
return new TcpHandler(resourceManager);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platforms>AnyCPU;x64;x86</Platforms>
<Authors>EasyMicroservices</Authors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>0.0.0.12</Version>
<Version>0.0.0.13</Version>
<Description>Laboratory of http client.</Description>
<Copyright>[email protected]</Copyright>
<PackageTags>test,tests,http,https,httpclient,laboratory</PackageTags>
Expand Down
59 changes: 59 additions & 0 deletions src/CSharp/EasyMicroservices.Laboratory/Engine/Net/BaseHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using EasyMicroservices.Laboratory.Constants;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace EasyMicroservices.Laboratory.Engine.Net
{
/// <summary>
/// Handle the Tcp services
/// </summary>
public abstract class BaseHandler
{
/// <summary>
///
/// </summary>
public BaseHandler(ResourceManager resourceManager)
{
_requestHandler = new RequestHandler(resourceManager);
}

/// <summary>
///
/// </summary>
protected readonly RequestHandler _requestHandler;
/// <summary>
/// Start the Tcp listener
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
public abstract Task Start(int port);
/// <summary>
///
/// </summary>
/// <returns></returns>
public abstract Task<int> Start();

/// <summary>
///
/// </summary>
public abstract void Stop();


static Random _random = new Random();
/// <summary>
/// start on any random port
/// </summary>
/// <returns>port to listen</returns>
public int GetRandomPort()
{
return _random.Next(1111, 9999);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
using EasyMicroservices.Laboratory.IO;
using EasyMicroservices.Utilities.Constants;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Sockets;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace EasyMicroservices.Laboratory.Engine.Net.Http
{
/// <summary>
/// Http protocol handler of Laboratory
///
/// </summary>
public class HttpHandler : TcpHandler
public class HttpHandler : HttpHandlerBase
{
/// <summary>
///
Expand All @@ -23,45 +21,46 @@ public HttpHandler(ResourceManager resourceManager) : base(resourceManager)

}


/// <summary>
/// Handle Tcp client of a http client
///
/// </summary>
/// <param name="tcpClient"></param>
/// <param name="httpClient"></param>
/// <returns></returns>
protected override async Task HandleTcpClient(TcpClient tcpClient)
/// <exception cref="NotImplementedException"></exception>
protected override async Task HandleHttpClient(HttpListenerContext httpClient)
{
using var stream = new PipelineStream(tcpClient.GetStream());
string firstLine = await ReadLineAsync(stream);
var reader = new StreamReader(httpClient.Request.InputStream);
var requestBody = await reader.ReadToEndAsync();
var firstLine = $"{httpClient.Request.HttpMethod} {httpClient.Request.RawUrl} HTTP/{httpClient.Request.ProtocolVersion}";
var headers = httpClient.Request.Headers.AllKeys.Select(x => new { Key = x, Value = httpClient.Request.Headers[x] }).ToDictionary((x) => x.Key, (v) => v.Value);
StringBuilder fullBody = new StringBuilder();
Dictionary<string, string> headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
fullBody.AppendLine(firstLine);
//read headers
while (true)
foreach (var item in headers.OrderBy(x => x.Key))
{
var line = await ReadLineAsync(stream);
if (string.IsNullOrEmpty(line))
break;
var headerValue = line.Split(new char[] { ':' }, 2);
headers.TryAddItem(headerValue[0], headerValue[1].Trim());
fullBody.AppendLine(line);
fullBody.AppendLine($"{item.Key}: {item.Value}");
}
int contentLength = 0;
if (headers.TryGetValue(HttpHeadersConstants.ContentLength, out string contentLengthValue))
fullBody.Append(requestBody);
var responseBody = await WriteResponseAsync(firstLine, headers, requestBody, fullBody);
using (var responseReader = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(responseBody))))
{
contentLength = int.Parse(contentLengthValue);
}
await responseReader.ReadLineAsync();
do
{
var line = await responseReader.ReadLineAsync();
if (string.IsNullOrEmpty(line))
break;
var header = line.Split(':');
if (header[0].Equals("content-length", StringComparison.OrdinalIgnoreCase))
continue;
httpClient.Response.AddHeader(header[0], header[1]);
}
while (true);
var body = await responseReader.ReadToEndAsync();
var bytes = Encoding.UTF8.GetBytes(body);
httpClient.Response.ContentLength64 = bytes.Length;

string requestBody = "";
if (contentLength > 0)
{
var buffer = await ReadBlockAsync(stream, contentLength);
requestBody = Encoding.UTF8.GetString(buffer);
fullBody.AppendLine();
fullBody.Append(requestBody);
await httpClient.Response.OutputStream.WriteAsync(bytes, 0, bytes.Length);
}
await WriteResponseAsync(firstLine, headers, requestBody, fullBody, stream);
tcpClient.Client.Shutdown(SocketShutdown.Send);
}
}
}
Loading

0 comments on commit af6e28a

Please sign in to comment.