Skip to content

Commit

Permalink
Add RequestMethodExtractor
Browse files Browse the repository at this point in the history
  • Loading branch information
staticage committed Jun 12, 2013
1 parent e107dc4 commit 0cedab8
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 101 deletions.
Binary file modified Radish.v11.suo
Binary file not shown.
7 changes: 6 additions & 1 deletion Radish/AbstractRequestMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
namespace Radish
{
public abstract class AbstractRequestMatcher
public interface IRequestMatcher
{
bool IsMatch(IHttpRequest request);
}

public abstract class AbstractRequestMatcher : IRequestMatcher
{
public abstract bool IsMatch(IHttpRequest request);

Expand Down
2 changes: 1 addition & 1 deletion Radish/EqualRequestMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public EqualRequestMatcher(IRequestExtractor extractor, string expected)

public override bool IsMatch(IHttpRequest request)
{
throw new NotImplementedException();
return _extractor.Extract(request).Equals(_expected);
}
}
}
8 changes: 8 additions & 0 deletions Radish/Extractors/RequestUriExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ public string Extract(IHttpRequest request)
throw new NotImplementedException();
}
}

public class RequestMethodExtractor : IRequestExtractor
{
public string Extract(IHttpRequest request)
{
throw new NotImplementedException();
}
}
}
100 changes: 3 additions & 97 deletions Radish/HttpServer.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;

namespace Radish
{
public class Setting
{
public AbstractRequestMatcher RequestMatcher { get; set; }
public IRequestMatcher RequestMatcher { get; set; }
public ResponseSetting ResponseSetting { get; set; }
}

Expand All @@ -33,105 +31,13 @@ public HttpServer()
_settings = new List<Setting>();
}

public HttpHandlerSetting When(Func<RequestSetting, AbstractRequestMatcher> requestMatcherExpression)
public HttpHandlerSetting When(Func<RequestSetting, IRequestMatcher> requestMatcherExpression)
{
var setting = new Setting();
setting.RequestMatcher = requestMatcherExpression(new RequestSetting());

_settings.Add(setting);
return this;
}
}

public class HttpServerEngine : IDisposable
{
private readonly HttpListener _listener;
private readonly Thread _listenerThread;
private readonly Thread[] _workers;
private readonly ManualResetEvent _stop, _ready;
private readonly Queue<HttpListenerContext> _queue;

public HttpServerEngine(int maxThreads)
{
_workers = new Thread[maxThreads];
_queue = new Queue<HttpListenerContext>();
_stop = new ManualResetEvent(false);
_ready = new ManualResetEvent(false);
_listener = new HttpListener();
_listenerThread = new Thread(HandleRequests);
}

public void Start(int port)
{
_listener.Prefixes.Add(String.Format(@"http://+:{0}/", port));
_listener.Start();
_listenerThread.Start();

for (int i = 0; i < _workers.Length; i++)
{
_workers[i] = new Thread(Worker);
_workers[i].Start();
}
}

public void Dispose()
{ Stop(); }

public void Stop()
{
_stop.Set();
_listenerThread.Join();
foreach (Thread worker in _workers)
worker.Join();
_listener.Stop();
}

private void HandleRequests()
{
while (_listener.IsListening)
{
var context = _listener.BeginGetContext(ContextReady, null);

if (0 == WaitHandle.WaitAny(new[] { _stop, context.AsyncWaitHandle }))
return;
}
}

private void ContextReady(IAsyncResult ar)
{
try
{
lock (_queue)
{
_queue.Enqueue(_listener.EndGetContext(ar));
_ready.Set();
}
}
catch { return; }
}

private void Worker()
{
WaitHandle[] wait = new[] { _ready, _stop };
while (0 == WaitHandle.WaitAny(wait))
{
HttpListenerContext context;
lock (_queue)
{
if (_queue.Count > 0)
context = _queue.Dequeue();
else
{
_ready.Reset();
continue;
}
}

try { ProcessRequest(context); }
catch (Exception e) { Console.Error.WriteLine(e); }
}
return this;
}

public event Action<HttpListenerContext> ProcessRequest;
}
}
99 changes: 99 additions & 0 deletions Radish/HttpServerEngine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;

namespace Radish
{
public class HttpServerEngine : IDisposable
{
private readonly HttpListener _listener;
private readonly Thread _listenerThread;
private readonly Thread[] _workers;
private readonly ManualResetEvent _stop, _ready;
private readonly Queue<HttpListenerContext> _queue;

public HttpServerEngine(int maxThreads)
{
_workers = new Thread[maxThreads];
_queue = new Queue<HttpListenerContext>();
_stop = new ManualResetEvent(false);
_ready = new ManualResetEvent(false);
_listener = new HttpListener();
_listenerThread = new Thread(HandleRequests);
}

public void Start(int port)
{
_listener.Prefixes.Add(String.Format(@"http://+:{0}/", port));
_listener.Start();
_listenerThread.Start();

for (int i = 0; i < _workers.Length; i++)
{
_workers[i] = new Thread(Worker);
_workers[i].Start();
}
}

public void Dispose()
{ Stop(); }

public void Stop()
{
_stop.Set();
_listenerThread.Join();
foreach (Thread worker in _workers)
worker.Join();
_listener.Stop();
}

private void HandleRequests()
{
while (_listener.IsListening)
{
var context = _listener.BeginGetContext(ContextReady, null);

if (0 == WaitHandle.WaitAny(new[] { _stop, context.AsyncWaitHandle }))
return;
}
}

private void ContextReady(IAsyncResult ar)
{
try
{
lock (_queue)
{
_queue.Enqueue(_listener.EndGetContext(ar));
_ready.Set();
}
}
catch { return; }
}

private void Worker()
{
WaitHandle[] wait = new[] { _ready, _stop };
while (0 == WaitHandle.WaitAny(wait))
{
HttpListenerContext context;
lock (_queue)
{
if (_queue.Count > 0)
context = _queue.Dequeue();
else
{
_ready.Reset();
continue;
}
}

try { ProcessRequest(context); }
catch (Exception e) { Console.Error.WriteLine(e); }
}
}

public event Action<HttpListenerContext> ProcessRequest;
}
}
1 change: 1 addition & 0 deletions Radish/Radish.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<ItemGroup>
<Compile Include="AbstractRequestMatcher.cs" />
<Compile Include="AndRequestMatcher.cs" />
<Compile Include="HttpServerEngine.cs" />
<Compile Include="IResponseWriter.cs" />
<Compile Include="EqualRequestMatcher.cs" />
<Compile Include="HttpServer.cs" />
Expand Down
3 changes: 1 addition & 2 deletions Radish/RequestMatcherSetting.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
namespace Radish
{
public class RequestMatcherSetting
public abstract class RequestMatcherSetting
{
protected IRequestExtractor _extractor;


public AbstractRequestMatcher Is(string expected)
{
return new EqualRequestMatcher(_extractor, expected);
Expand Down
9 changes: 9 additions & 0 deletions Radish/RequestSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@ public RequestMatcherSetting Uri
return this;
}
}

public RequestMatcherSetting Method
{
get
{
_extractor = new RequestMethodExtractor();
return this;
}
}
}
}

0 comments on commit 0cedab8

Please sign in to comment.