Commit 1c4dfbe1 authored by Shani Elharrar's avatar Shani Elharrar

Some refactoring.

parent 5bbb50e0
......@@ -17,7 +17,6 @@
*/
using System;
using System.Net.Cache;
using System.Text;
using System.Threading.Tasks;
using uhttpsharp;
......
......@@ -45,7 +45,7 @@ namespace uhttpsharpdemo
httpServer.Use(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, 82)));
//httpServer.Use(new ListenerSslDecorator(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, 443)), serverCertificate));
httpServer.Use(new SessionHandler<DateTime>(() => DateTime.Now));
//httpServer.Use(new SessionHandler<DateTime>(() => DateTime.Now));
httpServer.Use(new ExceptionHandler());
httpServer.Use(new TimingHandler());
......
......@@ -9,6 +9,7 @@ namespace uhttpsharp.Clients
Stream Stream { get; }
bool Connected { get; }
void Close();
EndPoint RemoteEndPoint { get; }
......
......@@ -16,6 +16,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting.Contexts;
using System.Text;
using log4net;
using System.Net;
......@@ -31,7 +34,7 @@ using uhttpsharp.RequestProviders;
namespace uhttpsharp
{
internal sealed class HttpClient
internal sealed class HttpClientHandler
{
private const string CrLf = "\r\n";
private static readonly byte[] CrLfBuffer = Encoding.UTF8.GetBytes(CrLf);
......@@ -39,18 +42,19 @@ namespace uhttpsharp
private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly IClient _client;
private readonly Func<IHttpContext, Task> _requestHandler;
private readonly StreamReader _inputStream;
private readonly StreamWriter _outputStream;
private readonly IList<IHttpRequestHandler> _requestHandlers;
private readonly IHttpRequestProvider _requestProvider;
private readonly EndPoint _remoteEndPoint;
private DateTime _lastOperationTime;
public HttpClient(IClient client, IList<IHttpRequestHandler> requestHandlers, IHttpRequestProvider requestProvider)
public HttpClientHandler(IClient client, Func<IHttpContext, Task> requestHandler, IHttpRequestProvider requestProvider)
{
_remoteEndPoint = client.RemoteEndPoint;
_client = client;
_requestHandlers = requestHandlers;
_requestProvider = requestProvider;
_requestHandler = requestHandler;
_requestProvider = requestProvider;
var bufferedStream = new BufferedStream(_client.Stream);
......@@ -60,6 +64,8 @@ namespace uhttpsharp
Logger.InfoFormat("Got Client {0}", _remoteEndPoint);
Task.Factory.StartNew(Process);
UpdateLastOperationTime();
}
private async void Process()
......@@ -72,41 +78,20 @@ namespace uhttpsharp
if (request != null)
{
UpdateLastOperationTime();
var context = new HttpContext(request);
Logger.InfoFormat("{1} : Got request {0}", request.Uri, _client.RemoteEndPoint);
var getResponse = BuildHandlers(context)();
await getResponse.ConfigureAwait(false);
var response = context.Response;
await _requestHandler(context).ConfigureAwait(false);
if (response != null)
if (context.Response != null)
{
// Headers
await response.WriteHeaders(_outputStream).ConfigureAwait(false);
// Cookies
if (context.Cookies.Touched)
{
await _outputStream.WriteAsync(context.Cookies.ToCookieData())
.ConfigureAwait(false);
await _outputStream.FlushAsync().ConfigureAwait(false);
}
// Empty Line
await _outputStream.BaseStream.WriteAsync(CrLfBuffer, 0, CrLfBuffer.Length).ConfigureAwait(false);
// Body
await response.WriteResponse(_outputStream).ConfigureAwait(false);
if (!request.Headers.KeepAliveConnection() || response.CloseConnection)
{
_client.Close();
}
await WriteResponse(context);
}
UpdateLastOperationTime();
}
else
{
......@@ -114,32 +99,90 @@ namespace uhttpsharp
}
}
}
catch (SocketException)
catch (Exception e)
{
// Hate people who make bad calls.
Logger.Warn(string.Format("Error while serving : {0}", _remoteEndPoint), e);
_client.Close();
}
catch (IOException)
Logger.InfoFormat("Lost Client {0}", _remoteEndPoint);
}
private async Task WriteResponse(HttpContext context)
{
IHttpResponse response = context.Response;
IHttpRequest request = context.Request;
// Headers
await response.WriteHeaders(_outputStream).ConfigureAwait(false);
// Cookies
if (context.Cookies.Touched)
{
// Socket exceptions on read will be re-thrown as IOException by BufferedStream
await _outputStream.WriteAsync(context.Cookies.ToCookieData())
.ConfigureAwait(false);
await _outputStream.FlushAsync().ConfigureAwait(false);
}
catch (Exception e)
// Empty Line
await _outputStream.BaseStream.WriteAsync(CrLfBuffer, 0, CrLfBuffer.Length).ConfigureAwait(false);
// Body
await response.WriteResponse(_outputStream).ConfigureAwait(false);
if (!request.Headers.KeepAliveConnection() || response.CloseConnection)
{
// Hate people who make bad calls.
Logger.Warn(string.Format("Error while serving : {0} : {1}{2}", _remoteEndPoint, Environment.NewLine, e));
_client.Close();
}
}
Logger.InfoFormat("Lost Client {0}", _remoteEndPoint);
public IClient Client
{
get { return _client; }
}
public void ForceClose()
{
_client.Close();
}
private Func<Task> BuildHandlers(IHttpContext context, int index = 0)
public DateTime LastOperationTime
{
if (index > _requestHandlers.Count)
get
{
return _lastOperationTime;
}
}
private void UpdateLastOperationTime()
{
// _lastOperationTime = DateTime.Now;
}
}
public static class RequestHandlersAggregateExtensions
{
public static Func<IHttpContext, Task> Aggregate(this IList<IHttpRequestHandler> handlers)
{
return handlers.Aggregate(0);
}
private static Func<IHttpContext, Task> Aggregate(this IList<IHttpRequestHandler> handlers, int index)
{
if (index == handlers.Count)
{
return null;
}
return () => _requestHandlers[index].Handle(context, BuildHandlers(context, index + 1));
var currentHandler = handlers[index];
var nextHandler = handlers.Aggregate(index + 1);
return context => currentHandler.Handle(context, () => nextHandler(context));
}
}
}
\ No newline at end of file
......@@ -100,7 +100,7 @@ namespace uhttpsharp
{
ContentStream.Position = 0;
await ContentStream.CopyToAsync(writer.BaseStream).ConfigureAwait(false);
await writer.BaseStream.FlushAsync();
await writer.BaseStream.FlushAsync().ConfigureAwait(false);
}
public bool CloseConnection
......
......@@ -34,7 +34,6 @@ namespace uhttpsharp
private readonly IList<IHttpRequestHandler> _handlers = new List<IHttpRequestHandler>();
private readonly IList<IHttpListener> _listeners = new List<IHttpListener>();
private readonly IHttpRequestProvider _requestProvider;
......@@ -69,11 +68,13 @@ namespace uhttpsharp
private async void Listen(IHttpListener listener)
{
var aggregatedHandler = _handlers.Aggregate();
while (_isActive)
{
try
{
new HttpClient(await listener.GetClient().ConfigureAwait(false), _handlers, _requestProvider);
new HttpClientHandler(await listener.GetClient().ConfigureAwait(false), aggregatedHandler, _requestProvider);
}
catch (Exception e)
{
......
......@@ -43,7 +43,7 @@ namespace uhttpsharp.RequestProviders
}
IHttpHeaders headers = new HttpHeaders(headersRaw);
IHttpHeaders post = await GetPostData(streamReader, headers);
IHttpHeaders post = await GetPostData(streamReader, headers).ConfigureAwait(false);
return new HttpRequest(headers, httpMethod, httpProtocol, uri,
uri.OriginalString.Split(Separators, StringSplitOptions.RemoveEmptyEntries), queryString, post);
......@@ -70,7 +70,7 @@ namespace uhttpsharp.RequestProviders
IHttpHeaders post;
if (headers.TryGetByName("content-length", out postContentLength))
{
post = await HttpHeaders.FromPost(streamReader, postContentLength);
post = await HttpHeaders.FromPost(streamReader, postContentLength).ConfigureAwait(false);
}
else
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment