126 lines
3.0 KiB
C#
126 lines
3.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.Net.Sockets;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace BlogServer.WebServer
|
|
{
|
|
internal class HttpRequestPath
|
|
{
|
|
private HttpRequestFilter _head;
|
|
private HttpRequestFilter _tail;
|
|
private HttpRequestFilter _default;
|
|
|
|
private ArrayList _handlers = new ArrayList();
|
|
|
|
|
|
public HttpRequestPath()
|
|
{
|
|
_default = new DefaultFilter(this);
|
|
}
|
|
|
|
public void Register(Regex pattern, TrivialWebServer tws)
|
|
{
|
|
tws.RegisterHandler(pattern, new RequestHandler(Handler));
|
|
}
|
|
|
|
public void AddFilter(HttpRequestFilter filter)
|
|
{
|
|
if (_head == null)
|
|
_head = filter;
|
|
|
|
if (_tail != null)
|
|
{
|
|
_tail.SetNextRequestFilter(filter);
|
|
}
|
|
_tail = filter;
|
|
_tail.SetNextRequestFilter(_default);
|
|
}
|
|
|
|
public void AddHandler(HttpRequestHandler handler)
|
|
{
|
|
_handlers.Add(handler);
|
|
}
|
|
|
|
private bool Handler(string method, string uri, HttpHeaders headers, SocketReader reader, Socket socket)
|
|
{
|
|
if (_handlers.Count == 0)
|
|
return false;
|
|
|
|
string path, querystring;
|
|
int qindex = uri.IndexOf('?');
|
|
if (qindex < 0)
|
|
{
|
|
path = uri;
|
|
querystring = null;
|
|
}
|
|
else
|
|
{
|
|
path = uri.Substring(0, qindex);
|
|
querystring = qindex == (uri.Length - 1) ? "" : uri.Substring(qindex + 1);
|
|
}
|
|
|
|
MemoryStream requestBodyStream = new MemoryStream();
|
|
byte[] buffer = new byte[8192];
|
|
int bytesRead;
|
|
while (0 != (bytesRead = reader.Read(buffer, 0, buffer.Length)))
|
|
{
|
|
requestBodyStream.Write(buffer, 0, bytesRead);
|
|
}
|
|
requestBodyStream.Seek(0, SeekOrigin.Begin);
|
|
|
|
Stream readOnlyRequestBodyStream = new ReadOnlyStream(requestBodyStream);
|
|
readOnlyRequestBodyStream.Seek(0, SeekOrigin.Begin);
|
|
|
|
Request request = new Request(method, path, querystring, headers, readOnlyRequestBodyStream);
|
|
Response response = new Response(new MemoryStream());
|
|
if (StartFilter.Filter(request, response))
|
|
{
|
|
response.Stream.Seek(0, SeekOrigin.Begin);
|
|
StreamHelper.Transfer(response.Stream, new SocketStream(socket, false));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private HttpRequestFilter StartFilter
|
|
{
|
|
get { return _head != null ? _head : _default; }
|
|
}
|
|
|
|
private bool InvokeHandlers(Request request, Response response)
|
|
{
|
|
foreach (HttpRequestHandler handler in _handlers)
|
|
{
|
|
request.RequestBody.Seek(0, SeekOrigin.Begin);
|
|
|
|
Response tempResponse = new Response(new MemoryStream());
|
|
if (handler.Handle(request, tempResponse))
|
|
{
|
|
tempResponse.Stream.Seek(0, SeekOrigin.Begin);
|
|
StreamHelper.Transfer(tempResponse.Stream, response.Stream);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private class DefaultFilter : HttpRequestFilter
|
|
{
|
|
private readonly HttpRequestPath _parent;
|
|
|
|
public DefaultFilter(HttpRequestPath parent)
|
|
{
|
|
_parent = parent;
|
|
}
|
|
|
|
protected internal override bool Filter(Request request, Response response)
|
|
{
|
|
return _parent.InvokeHandlers(request, response);
|
|
}
|
|
}
|
|
}
|
|
}
|