diff --git a/README.md b/README.md
index d213a60..1ce9b49 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,18 @@
A very lightweight & simple embedded http server for c#
+## In this branch
+
+A few changes I'm making for [another project](https://github.com/sandrock/MarkDownBrowser/):
+
+* Allow multiple instances (on multiple TCP/IP ports)
+ * Bye bye static stuff
+* Allow bit of IoC
+* Convert the HttpHandler class to a IHttpHandler interface
+* Create a HttpContext class to simplify IHttpHandler
+
+## License
+
Copyright (C) 2011 uhttpsharp project
This library is free software; you can redistribute it and/or
diff --git a/uhttpsharp-demo/AboutHandler.cs b/uhttpsharp-demo/AboutHandler.cs
index 5bbc501..b7fb880 100644
--- a/uhttpsharp-demo/AboutHandler.cs
+++ b/uhttpsharp-demo/AboutHandler.cs
@@ -23,9 +23,9 @@ namespace uhttpsharpdemo
[HttpRequestHandlerAttributes("about")]
public class AboutHandler : HttpRequestHandler
{
- public override HttpResponse Handle(HttpRequest httpRequest)
+ public override HttpResponse Handle(HttpContext context)
{
- return HttpResponse.CreateWithMessage(HttpResponseCode.Ok, "Sample http-request-handler");
+ return HttpResponse.CreateWithMessage(context, HttpResponseCode.Ok, "Sample http-request-handler");
}
}
}
\ No newline at end of file
diff --git a/uhttpsharp-demo/ConsoleTraceListener.cs b/uhttpsharp-demo/ConsoleTraceListener.cs
new file mode 100644
index 0000000..a176edd
--- /dev/null
+++ b/uhttpsharp-demo/ConsoleTraceListener.cs
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 uhttpsharp project - http://github.com/raistlinthewiz/uhttpsharp
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace uhttpsharpdemo
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
+ using System.Text;
+
+ ///
+ /// Logs tracing event to the with coloration.
+ ///
+ public class ConsoleTraceListener : TraceListener
+ {
+ private readonly object syncRoot = new object();
+
+ public static ConsoleTraceListener Bind()
+ {
+ var listener = Trace.Listeners.OfType().FirstOrDefault();
+
+ if (listener == null)
+ {
+ Trace.Listeners.Add(listener = new ConsoleTraceListener());
+ }
+
+ return listener;
+ }
+
+ public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
+ {
+ base.TraceEvent(eventCache, source, eventType, id, message);
+
+ lock (this.syncRoot)
+ {
+ var foreg = Console.ForegroundColor;
+ var backg = Console.BackgroundColor;
+
+ switch (eventType)
+ {
+ case TraceEventType.Critical:
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.BackgroundColor = ConsoleColor.Red;
+ break;
+
+ case TraceEventType.Error:
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.BackgroundColor = ConsoleColor.White;
+ break;
+
+ case TraceEventType.Verbose:
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.BackgroundColor = ConsoleColor.White;
+ break;
+
+ case TraceEventType.Warning:
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.BackgroundColor = ConsoleColor.Black;
+ break;
+
+ case TraceEventType.Information:
+ case TraceEventType.Resume:
+ case TraceEventType.Start:
+ case TraceEventType.Stop:
+ case TraceEventType.Suspend:
+ case TraceEventType.Transfer:
+ default:
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.BackgroundColor = ConsoleColor.Black;
+ break;
+ }
+
+ Console.Write(eventType.ToString().Substring(0, 4).ToUpperInvariant() + " ");
+
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.BackgroundColor = ConsoleColor.Black;
+
+ Console.WriteLine(message);
+
+ Console.ForegroundColor = foreg;
+ Console.BackgroundColor = backg;
+ }
+ }
+
+ public override void Write(string message)
+ {
+ }
+
+ public override void WriteLine(string message)
+ {
+ }
+ }
+}
diff --git a/uhttpsharp-demo/ErrorHandler.cs b/uhttpsharp-demo/ErrorHandler.cs
index 92d38ea..5f83264 100644
--- a/uhttpsharp-demo/ErrorHandler.cs
+++ b/uhttpsharp-demo/ErrorHandler.cs
@@ -16,16 +16,16 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-using uhttpsharp;
-
namespace uhttpsharpdemo
{
+ using uhttpsharp;
+
[HttpRequestHandlerAttributes("404")]
public class ErrorHandler : HttpRequestHandler
{
- public override HttpResponse Handle(HttpRequest httpRequest)
+ public override HttpResponse Handle(HttpContext context)
{
- return new HttpResponse(HttpResponseCode.NotFound, "These are not the droids you are looking for.");
+ return new HttpResponse(context, HttpResponseCode.NotFound, "These are not the droids you are looking for.");
}
}
}
\ No newline at end of file
diff --git a/uhttpsharp-demo/FileHandler.cs b/uhttpsharp-demo/FileHandler.cs
index 3450fb8..cf2cf12 100644
--- a/uhttpsharp-demo/FileHandler.cs
+++ b/uhttpsharp-demo/FileHandler.cs
@@ -33,16 +33,26 @@ static FileHandler()
{
DefaultMimeType = "text/plain";
MimeTypes = new Dictionary
- {
- {".css", "text/css"},
- {".gif", "image/gif"},
- {".htm", "text/html"},
- {".html", "text/html"},
- {".jpg", "image/jpeg"},
- {".js", "application/javascript"},
- {".png", "image/png"},
- {".xml", "application/xml"},
- };
+ {
+ {".css", "text/css"},
+ {".gif", "image/gif"},
+ {".htm", "text/html"},
+ {".html", "text/html"},
+ {".jpg", "image/jpeg"},
+ {".js", "application/javascript"},
+ {".png", "image/png"},
+ {".xml", "application/xml"},
+ };
+ }
+
+ public override HttpResponse Handle(HttpContext context)
+ {
+ var httpRoot = Path.GetFullPath(HttpRootDirectory ?? ".");
+ var requestPath = context.Request.Uri.AbsolutePath.TrimStart('/');
+ var path = Path.GetFullPath(Path.Combine(httpRoot, requestPath));
+ if (!File.Exists(path))
+ return null;
+ return new HttpResponse(context, GetContentType(path), File.OpenRead(path));
}
private string GetContentType(string path)
@@ -52,14 +62,5 @@ private string GetContentType(string path)
return MimeTypes[extension];
return DefaultMimeType;
}
- public override HttpResponse Handle(HttpRequest httpRequest)
- {
- var httpRoot = Path.GetFullPath(HttpRootDirectory ?? ".");
- var requestPath = httpRequest.Uri.AbsolutePath.TrimStart('/');
- var path = Path.GetFullPath(Path.Combine(httpRoot, requestPath));
- if (!File.Exists(path))
- return null;
- return new HttpResponse(GetContentType(path), File.OpenRead(path));
- }
}
}
\ No newline at end of file
diff --git a/uhttpsharp-demo/IndexHandler.cs b/uhttpsharp-demo/IndexHandler.cs
index e6a31ed..e361758 100644
--- a/uhttpsharp-demo/IndexHandler.cs
+++ b/uhttpsharp-demo/IndexHandler.cs
@@ -23,9 +23,9 @@ namespace uhttpsharpdemo
[HttpRequestHandlerAttributes("")]
public class IndexHandler : HttpRequestHandler
{
- public override HttpResponse Handle(HttpRequest httpRequest)
+ public override HttpResponse Handle(HttpContext context)
{
- return new HttpResponse(HttpResponseCode.Ok, "Welcome to the Index. ☺");
+ return new HttpResponse(context, HttpResponseCode.Ok, "Welcome to the Index. ☺");
}
}
}
\ No newline at end of file
diff --git a/uhttpsharp-demo/Program.cs b/uhttpsharp-demo/Program.cs
index a70866d..051cd4f 100644
--- a/uhttpsharp-demo/Program.cs
+++ b/uhttpsharp-demo/Program.cs
@@ -19,6 +19,7 @@
using System;
using System.Net.Sockets;
using uhttpsharp;
+using System.Net;
namespace uhttpsharpdemo
{
@@ -26,12 +27,15 @@ internal static class Program
{
private static void Main()
{
+ ConsoleTraceListener.Bind();
+
+ HttpServer server = null;
for (var port = 8000; port <= 65535; ++port)
{
- HttpServer.Instance.Port = port;
+ server = new HttpServer(IPAddress.Loopback, port);
try
{
- HttpServer.Instance.StartUp();
+ server.Start();
}
catch (SocketException)
{
@@ -39,7 +43,13 @@ private static void Main()
}
break;
}
+
+ Console.WriteLine("Hit return to exit");
Console.ReadLine();
+
+ Console.WriteLine("Stopping...");
+ server.Dispose(); // TODO: this should be waiting for requests to end
+ Console.WriteLine("Stopped.");
}
}
}
\ No newline at end of file
diff --git a/uhttpsharp-demo/uhttpsharp-demo.csproj b/uhttpsharp-demo/uhttpsharp-demo.csproj
index 9c70de9..6cbdea9 100644
--- a/uhttpsharp-demo/uhttpsharp-demo.csproj
+++ b/uhttpsharp-demo/uhttpsharp-demo.csproj
@@ -47,6 +47,7 @@
Properties\AssemblyCommon.cs
+
diff --git a/uhttpsharp/HttpClient.cs b/uhttpsharp/HttpClient.cs
index 37d59eb..049837e 100644
--- a/uhttpsharp/HttpClient.cs
+++ b/uhttpsharp/HttpClient.cs
@@ -16,27 +16,32 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-using System.IO;
-using System.Net.Sockets;
-using System.Threading;
-
namespace uhttpsharp
{
+ using System.IO;
+ using System.Net.Sockets;
+ using System.Threading;
+
public sealed class HttpClient
{
private readonly TcpClient _client;
private readonly Stream _inputStream;
private readonly Stream _outputStream;
private readonly HttpRouter _router;
+ private readonly HttpContext context;
- public HttpClient(TcpClient client)
+ public HttpClient(HttpContext context, TcpClient client)
{
- _client = client;
- _inputStream = new BufferedStream(_client.GetStream());
- _outputStream = _client.GetStream();
- _router = new HttpRouter();
+ this._client = client;
+ this.context = context;
+ this._inputStream = new BufferedStream(this._client.GetStream());
+ this._outputStream = this._client.GetStream();
+ this._router = new HttpRouter(); // TODO: extract router instantiation
- var clientThread = new Thread(Process) {IsBackground = true};
+ var clientThread = new Thread(this.Process)
+ {
+ IsBackground = true,
+ };
clientThread.Start();
}
@@ -54,22 +59,31 @@ private void Process()
// Socket exceptions on read will be re-thrown as IOException by BufferedStream
}
}
+
private void ProcessInternal()
{
while (_client.Connected)
{
var request = new HttpRequest(_inputStream);
- if (request.Valid)
+ request.Process(context);
+ this.context.Request = request;
+ if (request.IsValid)
{
- var response = _router.Route(request);
+ var response = _router.Route(context);
+ this.context.Response = response;
if (response != null)
{
- response.WriteResponse(_outputStream);
- if (response.CloseConnection) _client.Close();
+ response.WriteResponse(context, _outputStream);
+ if (response.CloseConnection)
+ {
+ _client.Close();
+ }
}
}
else
+ {
_client.Close();
+ }
}
}
}
diff --git a/uhttpsharp/HttpContext.cs b/uhttpsharp/HttpContext.cs
new file mode 100644
index 0000000..7444b55
--- /dev/null
+++ b/uhttpsharp/HttpContext.cs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 uhttpsharp project - http://github.com/raistlinthewiz/uhttpsharp
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace uhttpsharp
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ public class HttpContext
+ {
+ public HttpServer Server { get; set; }
+
+ public HttpRequest Request { get; set; }
+
+ public HttpResponse Response { get; set; }
+ }
+}
diff --git a/uhttpsharp/HttpRequest.cs b/uhttpsharp/HttpRequest.cs
index a16c4e1..20491e2 100644
--- a/uhttpsharp/HttpRequest.cs
+++ b/uhttpsharp/HttpRequest.cs
@@ -19,12 +19,13 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Diagnostics;
namespace uhttpsharp
{
public sealed class HttpRequest
{
- public bool Valid { get; private set; }
+ public bool IsValid { get; private set; }
public Dictionary Headers { get; private set; }
public HttpMethod HttpMethod { get; private set; }
public string HttpProtocol { get; private set; }
@@ -38,12 +39,12 @@ public HttpRequest(Stream stream)
{
Headers = new Dictionary();
_stream = stream;
- Process();
+ ////Process();
}
- private void Process()
+ internal void Process(HttpContext context)
{
- Valid = false;
+ IsValid = false;
// parse the http request
var request = ReadLine();
@@ -53,7 +54,7 @@ private void Process()
if (tokens.Length != 3)
{
- Console.WriteLine("httpserver: invalid http request.");
+ Trace.TraceError("httpserver: invalid http request.");
return;
}
@@ -69,10 +70,10 @@ private void Process()
HttpProtocol = tokens[2];
URL = tokens[1];
- Uri = new Uri("http://" + HttpServer.Instance.Address + "/" + URL.TrimStart('/'));
+ Uri = new Uri("http://" + context.Server.Address + "/" + URL.TrimStart('/'));
Parameters = new HttpRequestParameters(URL);
- Console.WriteLine(string.Format("[{0}:{1}] URL: {2}", HttpProtocol, HttpMethod, URL));
+ Trace.TraceInformation(string.Format("[{0}:{1}] URL: {2}", HttpProtocol, HttpMethod, URL));
// get the headers
string line;
@@ -83,7 +84,7 @@ private void Process()
Headers.Add(keys[0], keys[1]);
}
- Valid = true;
+ IsValid = true;
}
private string ReadLine()
diff --git a/uhttpsharp/HttpRequestHandler.cs b/uhttpsharp/HttpRequestHandler.cs
index f87c645..817f8c6 100644
--- a/uhttpsharp/HttpRequestHandler.cs
+++ b/uhttpsharp/HttpRequestHandler.cs
@@ -16,15 +16,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-using System;
-
namespace uhttpsharp
{
- public class HttpRequestHandler
+ using System;
+
+ public class HttpRequestHandler : IHttpHandler
{
- public virtual HttpResponse Handle(HttpRequest httpRequest)
+ public virtual HttpResponse Handle(HttpContext context)
{
- throw new NotImplementedException();
+ throw new NotSupportedException("This method must be overriden in a subclass.");
}
}
@@ -35,7 +35,7 @@ public class HttpRequestHandlerAttributes : Attribute
public HttpRequestHandlerAttributes(string functionName)
{
- Function = functionName;
+ this.Function = functionName;
}
}
}
\ No newline at end of file
diff --git a/uhttpsharp/HttpResponse.cs b/uhttpsharp/HttpResponse.cs
index 4317b1f..942ea68 100644
--- a/uhttpsharp/HttpResponse.cs
+++ b/uhttpsharp/HttpResponse.cs
@@ -42,15 +42,17 @@ public sealed class HttpResponse
public HttpResponseCode Code { get; private set; }
private Stream ContentStream { get; set; }
- public HttpResponse(HttpResponseCode code, string content)
- : this(code, "text/html; charset=utf-8", StringToStream(content))
+ public HttpResponse(HttpContext context, HttpResponseCode code, string content, string contentType = "text/html; charset=utf-8")
+ : this(context, code, contentType, StringToStream(content))
{
}
- public HttpResponse(string contentType, Stream contentStream)
- : this(HttpResponseCode.Ok, contentType, contentStream)
+
+ public HttpResponse(HttpContext context, string contentType, Stream contentStream)
+ : this(context, HttpResponseCode.Ok, contentType, contentStream)
{
}
- private HttpResponse(HttpResponseCode code, string contentType, Stream contentStream)
+
+ private HttpResponse(HttpContext context, HttpResponseCode code, string contentType, Stream contentStream)
{
Protocol = "HTTP/1.1";
ContentType = contentType;
@@ -60,14 +62,16 @@ private HttpResponse(HttpResponseCode code, string contentType, Stream contentSt
ContentStream = contentStream;
}
- public static HttpResponse CreateWithMessage(HttpResponseCode code, string message, string body = "")
+ public static HttpResponse CreateWithMessage(HttpContext context, HttpResponseCode code, string message, string body = "")
{
return new HttpResponse(
+ context,
code,
string.Format(
"{0}{1}
{0}{2}",
- HttpServer.Instance.Banner, message, body));
+ context.Server.Banner, message, body));
}
+
private static Stream StringToStream(string content)
{
var stream = new MemoryStream();
@@ -76,12 +80,13 @@ private static Stream StringToStream(string content)
writer.Flush();
return stream;
}
- public void WriteResponse(Stream stream)
+
+ public void WriteResponse(HttpContext context, Stream stream)
{
- var writer = new StreamWriter(stream) {NewLine = "\r\n"};
- writer.WriteLine("{0} {1} {2}", Protocol, (int) Code, _responseTexts[(int) Code]);
+ var writer = new StreamWriter(stream) { NewLine = "\r\n" };
+ writer.WriteLine("{0} {1} {2}", Protocol, (int)Code, _responseTexts[(int)Code]);
writer.WriteLine("Date: {0}", DateTime.UtcNow.ToString("R"));
- writer.WriteLine("Server: {0}", HttpServer.Instance.Banner);
+ writer.WriteLine("Server: {0}", context.Server.Banner);
writer.WriteLine("Connection: {0}", CloseConnection ? "close" : "Keep-Alive");
writer.WriteLine("Content-Type: {0}", ContentType);
writer.WriteLine("Content-Length: {0}", ContentStream.Length);
diff --git a/uhttpsharp/HttpRouter.cs b/uhttpsharp/HttpRouter.cs
index 27a5da0..a9710b7 100644
--- a/uhttpsharp/HttpRouter.cs
+++ b/uhttpsharp/HttpRouter.cs
@@ -19,61 +19,73 @@
using System;
using System.Collections.Generic;
using System.Reflection;
+using System.Diagnostics;
namespace uhttpsharp
{
- internal sealed class HttpRouter
+ public sealed class HttpRouter
{
- private readonly Dictionary _handlers = new Dictionary();
+ private readonly Dictionary _handlers = new Dictionary();
- public HttpRouter()
+ internal HttpRouter()
{
RegisterHandlers();
}
- private HttpResponse DefaultError()
+ private HttpResponse DefaultError(HttpContext context)
{
- return HttpResponse.CreateWithMessage(HttpResponseCode.NotFound, "Not Found");
+ return HttpResponse.CreateWithMessage(context, HttpResponseCode.NotFound, "Not Found");
}
- private HttpResponse DefaultIndex()
+
+ private HttpResponse DefaultIndex(HttpContext context)
{
- return HttpResponse.CreateWithMessage(HttpResponseCode.Ok, "Welcome to uhttpsharp!");
+ return HttpResponse.CreateWithMessage(context, HttpResponseCode.Ok, "Welcome to uhttpsharp!");
}
- public HttpResponse Route(HttpRequest request)
+
+ public HttpResponse Route(HttpContext context)
{
+ var request = context.Request;
var function = request.Parameters.Function;
return
- RouteToFunction(request, function) ??
- RouteToFunction(request, "*") ??
- (string.IsNullOrEmpty(function) ? (RouteToFunction(request, "") ?? DefaultIndex()) : null) ??
- RouteToFunction(request, "404") ??
- DefaultError();
+ RouteToFunction(context, function) ??
+ RouteToFunction(context, "*") ??
+ (string.IsNullOrEmpty(function) ? (RouteToFunction(context, "") ?? DefaultIndex(context)) : null) ??
+ RouteToFunction(context, "404") ??
+ DefaultError(context);
}
- private HttpResponse RouteToFunction(HttpRequest request, string function)
+
+ private HttpResponse RouteToFunction(HttpContext context, string function)
{
- HttpRequestHandler handler;
+ var request = context.Request;
+ IHttpHandler handler;
+
if (_handlers.TryGetValue(function, out handler))
- return handler.Handle(request);
+ {
+ context.Response = handler.Handle(context);
+ return context.Response;
+ }
+
return null;
}
+
private void RegisterHandlers()
{
- foreach (var t in Assembly.GetEntryAssembly().GetTypes())
+ foreach (var type in Assembly.GetEntryAssembly().GetTypes())
{
- if (t.IsSubclassOf(typeof(HttpRequestHandler)))
+ if (type.IsSubclassOf(typeof(HttpRequestHandler)))
{
try
{
- var attributes = t.GetCustomAttributes(typeof(HttpRequestHandlerAttributes), true);
+ var attributes = type.GetCustomAttributes(typeof(HttpRequestHandlerAttributes), true);
if (attributes.Length > 0)
{
- var handler = (HttpRequestHandler)Activator.CreateInstance(t);
+ var handler = (HttpRequestHandler)Activator.CreateInstance(type);
_handlers.Add(((HttpRequestHandlerAttributes)attributes[0]).Function, handler);
}
}
- catch (Exception e)
+ catch (Exception ex)
{
- Console.WriteLine(string.Format("Exception during activating the IHttpRequestHandler: {0} - {1}", t, e));
+ Trace.TraceError(string.Format("Exception during activating the IHttpRequestHandler: {0} - {1}", type, ex));
}
}
}
diff --git a/uhttpsharp/HttpServer.cs b/uhttpsharp/HttpServer.cs
index ee3ae38..4d60b6e 100644
--- a/uhttpsharp/HttpServer.cs
+++ b/uhttpsharp/HttpServer.cs
@@ -16,54 +16,117 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-using System;
-using System.Net;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Threading;
-
namespace uhttpsharp
{
- public sealed class HttpServer
- {
- public static readonly HttpServer Instance = new HttpServer();
+ using System;
+ using System.Net;
+ using System.Net.Sockets;
+ using System.Reflection;
+ using System.Threading;
+ using System.Diagnostics;
- public int Port = 80;
+ public class HttpServer : IDisposable
+ {
public string Banner = string.Empty;
+ private bool isDisposed;
+ private TcpListener listener;
+ private bool isActive;
+ private Thread serverThread;
+
+ public HttpServer(IPAddress address, int port)
+ {
+ this.Address = address;
+ this.Port = port;
+ this.Banner = string.Format("uhttpsharp {0}", Assembly.GetExecutingAssembly().GetName().Version);
+ this.Router = new HttpRouter();
+ }
- private TcpListener _listener;
- private bool _isActive;
+ public IPAddress Address { get; set; }
- public string Address
+ public int Port { get; set; }
+
+ public HttpRouter Router { get; private set; }
+
+ public void Start()
{
- get { return string.Format("{0}:{1}", IPAddress.Loopback, Port); }
+ if (this.isActive)
+ return;
+ this.listener = new TcpListener(IPAddress.Loopback, Port);
+ this.listener.Start();
+ this.serverThread = new Thread(Listen)
+ {
+ IsBackground = true,
+ };
+ this.serverThread.Start();
}
- private HttpServer()
+ public void Dispose()
{
- Banner = string.Format("uhttpsharp {0}", Assembly.GetExecutingAssembly().GetName().Version);
+ this.Dispose(true, TimeSpan.FromSeconds(60D));
+ GC.SuppressFinalize(this);
}
- public void StartUp()
+ public void Dispose(TimeSpan timeout)
{
- if (_isActive)
- return;
- _listener = new TcpListener(IPAddress.Loopback, Port);
- _listener.Start();
- var serverThread = new Thread(Listen) {IsBackground = true};
- serverThread.Start();
+ this.Dispose(true, timeout);
+ GC.SuppressFinalize(this);
+ }
+
+ public override string ToString()
+ {
+ return this.GetType().Name + " " + this.Address.ToString() + ":" + this.Port.ToString();
+ }
+
+ protected virtual void Dispose(bool disposing, TimeSpan timeout)
+ {
+ if (!this.isDisposed)
+ {
+ if (disposing)
+ {
+ this.isActive = false;
+
+ if (this.listener != null)
+ {
+ this.listener.Stop();
+ this.listener = null;
+ }
+
+ if (this.serverThread != null)
+ {
+ this.serverThread.Join(timeout);
+ this.serverThread = null;
+ }
+ }
+
+ this.isDisposed = true;
+ }
}
private void Listen()
{
- _isActive = true;
+ this.isActive = true;
- Console.WriteLine(string.Format("Embedded httpserver started.. [{0}:{1}]", IPAddress.Loopback, Port));
+ Trace.TraceInformation(this.ToString() + " is now listenning.");
- while (_isActive)
+ while (this.isActive)
{
- new HttpClient(_listener.AcceptTcpClient());
+ var context = new HttpContext
+ {
+ Server = this,
+ };
+ try
+ {
+ var client = listener.AcceptTcpClient();
+ new HttpClient(context, client);
+ }
+ catch (SocketException ex)
+ {
+ // "A blocking operation was interrupted by a call to WSACancelBlockingCall"
+ // occurs during shutdown
+ }
}
+
+ Trace.TraceInformation(this.ToString() + " is not listenning anymore.");
}
}
}
\ No newline at end of file
diff --git a/uhttpsharp/IHttpHandler.cs b/uhttpsharp/IHttpHandler.cs
new file mode 100644
index 0000000..c7deb74
--- /dev/null
+++ b/uhttpsharp/IHttpHandler.cs
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 uhttpsharp project - http://github.com/raistlinthewiz/uhttpsharp
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace uhttpsharp
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ public interface IHttpHandler
+ {
+ HttpResponse Handle(HttpContext context);
+ }
+}
diff --git a/uhttpsharp/uhttpsharp.csproj b/uhttpsharp/uhttpsharp.csproj
index 0de8e1b..9aaba02 100644
--- a/uhttpsharp/uhttpsharp.csproj
+++ b/uhttpsharp/uhttpsharp.csproj
@@ -29,6 +29,7 @@
TRACE
prompt
4
+ bin\Release\uhttpsharp.xml
@@ -44,11 +45,13 @@
Properties\AssemblyCommon.cs
+
+