Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for http listener and improvement performance #12

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

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