Implement HttpRouter
parent
f2d95bc93d
commit
92b83af7f0
|
@ -10,6 +10,7 @@ using ln.http.cert;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using ln.http.session;
|
using ln.http.session;
|
||||||
|
using ln.http.exceptions;
|
||||||
|
|
||||||
|
|
||||||
namespace ln.http
|
namespace ln.http
|
||||||
|
@ -20,30 +21,36 @@ namespace ln.http
|
||||||
public static int defaultPort = 8080;
|
public static int defaultPort = 8080;
|
||||||
public static bool exclusivePortListener = false;
|
public static bool exclusivePortListener = false;
|
||||||
|
|
||||||
public HttpApplication DefaultApplication { get; set; }
|
public HttpRouter Router { get; set; }
|
||||||
public SessionCache SessionCache { get; set; }
|
|
||||||
|
|
||||||
public bool IsRunning => !shutdown && (threadPool.CurrentPoolSize > 0);
|
public bool IsRunning => !shutdown && (threadPool.CurrentPoolSize > 0);
|
||||||
public Func<HTTPServer,HTTPServerConnection> CreateServerConnection { get; set; }
|
|
||||||
|
|
||||||
public Logger Logger { get; set; }
|
public Logger Logger { get; set; }
|
||||||
|
|
||||||
bool shutdown = false;
|
bool shutdown = false;
|
||||||
|
|
||||||
List<Listener> listeners = new List<Listener>();
|
List<Listener> listeners = new List<Listener>();
|
||||||
public Listener[] Listeners => listeners.ToArray();
|
public Listener[] Listeners => listeners.ToArray();
|
||||||
|
|
||||||
Dictionary<URI, HttpApplication> applications = new Dictionary<URI, HttpApplication>();
|
|
||||||
|
|
||||||
DynamicPool threadPool;
|
DynamicPool threadPool;
|
||||||
public DynamicPool ThreadPool => threadPool;
|
public DynamicPool ThreadPool => threadPool;
|
||||||
|
|
||||||
public HTTPServer()
|
public HTTPServer()
|
||||||
{
|
{
|
||||||
Logger = Logger.Default;
|
Logger = Logger.Default;
|
||||||
|
|
||||||
SessionCache = new SessionCache();
|
|
||||||
threadPool = new DynamicPool(1024);
|
threadPool = new DynamicPool(1024);
|
||||||
}
|
}
|
||||||
|
public HTTPServer(HttpRouter router)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
Router = router;
|
||||||
|
}
|
||||||
|
public HTTPServer(Listener listener, HttpRouter router)
|
||||||
|
: this(router)
|
||||||
|
{
|
||||||
|
AddListener(listener);
|
||||||
|
}
|
||||||
|
public HTTPServer(Endpoint endpoint, HttpRouter router)
|
||||||
|
: this(new HttpListener(endpoint), router) { }
|
||||||
|
|
||||||
public void AddListener(Listener listener)
|
public void AddListener(Listener listener)
|
||||||
{
|
{
|
||||||
|
@ -76,22 +83,6 @@ namespace ln.http
|
||||||
AddListener(new HttpListener(endpoint));
|
AddListener(new HttpListener(endpoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddApplication(URI BaseURI, HttpApplication application)
|
|
||||||
{
|
|
||||||
applications[BaseURI] = application;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpApplication GetHttpApplication(URI baseURI)
|
|
||||||
{
|
|
||||||
HttpApplication application = DefaultApplication;
|
|
||||||
|
|
||||||
if (applications.ContainsKey(baseURI))
|
|
||||||
application = applications[baseURI];
|
|
||||||
|
|
||||||
return application;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
threadPool.Start();
|
threadPool.Start();
|
||||||
|
@ -124,14 +115,17 @@ namespace ln.http
|
||||||
if (httpRequest == null)
|
if (httpRequest == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
httpRequest.MakeCurrent();
|
HttpResponse response;
|
||||||
|
try
|
||||||
HttpApplication application = GetHttpApplication(new URI(httpRequest.BaseURI.ToString()));
|
{
|
||||||
|
response = Router.Route(httpRequest);
|
||||||
application.Authenticate(httpRequest);
|
} catch (HttpException httpExc)
|
||||||
application.Authorize(httpRequest);
|
{
|
||||||
|
response = new HttpResponse(httpRequest);
|
||||||
HttpResponse response = application.GetResponse(httpRequest);
|
response.StatusCode = httpExc.StatusCode;
|
||||||
|
response.StatusMessage = httpExc.Message;
|
||||||
|
response.ContentWriter.WriteLine(httpExc.Message);
|
||||||
|
}
|
||||||
|
|
||||||
if (response != null)
|
if (response != null)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +148,7 @@ namespace ln.http
|
||||||
HttpResponse httpResponse = new HttpResponse(httpRequest);
|
HttpResponse httpResponse = new HttpResponse(httpRequest);
|
||||||
httpResponse.StatusCode = 500;
|
httpResponse.StatusCode = 500;
|
||||||
httpResponse.ContentWriter.WriteLine("500 Internal Server Error");
|
httpResponse.ContentWriter.WriteLine("500 Internal Server Error");
|
||||||
|
httpResponse.ContentWriter.Flush();
|
||||||
|
|
||||||
connection.SendResponse(httpResponse);
|
connection.SendResponse(httpResponse);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,148 +10,148 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
namespace ln.http
|
namespace ln.http
|
||||||
{
|
{
|
||||||
public delegate void HTTPServerConnectionEvent(HTTPServerConnection connection);
|
//public delegate void HTTPServerConnectionEvent(HTTPServerConnection connection);
|
||||||
|
|
||||||
public class HTTPServerConnection : PoolJob
|
//public class HTTPServerConnection : PoolJob
|
||||||
{
|
//{
|
||||||
public static ThreadLocal<HTTPServerConnection> Current { get; } = new ThreadLocal<HTTPServerConnection>();
|
// public static ThreadLocal<HTTPServerConnection> Current { get; } = new ThreadLocal<HTTPServerConnection>();
|
||||||
static HashSet<HTTPServerConnection> currentConnections = new HashSet<HTTPServerConnection>();
|
// static HashSet<HTTPServerConnection> currentConnections = new HashSet<HTTPServerConnection>();
|
||||||
public static HTTPServerConnection[] CurrentConnections => currentConnections.ToArray();
|
// public static HTTPServerConnection[] CurrentConnections => currentConnections.ToArray();
|
||||||
|
|
||||||
public HTTPServer HTTPServer { get; }
|
// public HTTPServer HTTPServer { get; }
|
||||||
public TcpClient TcpClient { get; }
|
// public TcpClient TcpClient { get; }
|
||||||
|
|
||||||
public HttpRequest CurrentRequest { get; protected set; }
|
// public HttpRequest CurrentRequest { get; protected set; }
|
||||||
|
|
||||||
public event HTTPServerConnectionEvent AbortRequested;
|
// public event HTTPServerConnectionEvent AbortRequested;
|
||||||
|
|
||||||
public DateTime Created { get; }
|
// public DateTime Created { get; }
|
||||||
public DateTime Interpreted { get; set; }
|
// public DateTime Interpreted { get; set; }
|
||||||
public DateTime Finished { get; set; }
|
// public DateTime Finished { get; set; }
|
||||||
|
|
||||||
public HTTPServerConnection(HTTPServer httpServer,TcpClient tcpClient)
|
// public HTTPServerConnection(HTTPServer httpServer,TcpClient tcpClient)
|
||||||
{
|
// {
|
||||||
HTTPServer = httpServer;
|
// HTTPServer = httpServer;
|
||||||
TcpClient = tcpClient;
|
// TcpClient = tcpClient;
|
||||||
Created = DateTime.Now;
|
// Created = DateTime.Now;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public virtual HttpResponse GetResponse(HttpRequest httpRequest,HttpApplication httpApplication) => httpApplication.GetResponse(httpRequest);
|
// public virtual HttpResponse GetResponse(HttpRequest httpRequest,HttpApplication httpApplication) => httpApplication.GetResponse(httpRequest);
|
||||||
|
|
||||||
public virtual void Abort()
|
// public virtual void Abort()
|
||||||
{
|
// {
|
||||||
if (AbortRequested != null)
|
// if (AbortRequested != null)
|
||||||
AbortRequested(this);
|
// AbortRequested(this);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
public override void RunJob()
|
// public override void RunJob()
|
||||||
{
|
// {
|
||||||
HTTPServerConnection saveCurrent = Current.Value;
|
// HTTPServerConnection saveCurrent = Current.Value;
|
||||||
Current.Value = this;
|
// Current.Value = this;
|
||||||
lock (currentConnections)
|
// lock (currentConnections)
|
||||||
currentConnections.Add(this);
|
// currentConnections.Add(this);
|
||||||
|
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
setState("reading http request");
|
// setState("reading http request");
|
||||||
|
|
||||||
HttpReader httpReader = new HttpReader(TcpClient.GetStream());
|
// HttpReader httpReader = new HttpReader(TcpClient.GetStream());
|
||||||
httpReader.Read();
|
// httpReader.Read();
|
||||||
|
|
||||||
if (!httpReader.Valid)
|
// if (!httpReader.Valid)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
HttpResponse response = null;
|
// HttpResponse response = null;
|
||||||
|
|
||||||
using (CurrentRequest = new HttpRequest(this.HTTPServer,httpReader, (IPEndPoint)TcpClient.Client.LocalEndPoint))
|
// using (CurrentRequest = new HttpRequest(this.HTTPServer,httpReader, (IPEndPoint)TcpClient.Client.LocalEndPoint))
|
||||||
{
|
// {
|
||||||
Interpreted = DateTime.Now;
|
// Interpreted = DateTime.Now;
|
||||||
|
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
HttpApplication application = HTTPServer.GetHttpApplication(new URI(CurrentRequest.BaseURI.ToString()));
|
// HttpApplication application = HTTPServer.GetHttpApplication(new URI(CurrentRequest.BaseURI.ToString()));
|
||||||
|
|
||||||
application.Authenticate(CurrentRequest);
|
// application.Authenticate(CurrentRequest);
|
||||||
application.Authorize(CurrentRequest);
|
// application.Authorize(CurrentRequest);
|
||||||
|
|
||||||
setState("handling http request");
|
// setState("handling http request");
|
||||||
|
|
||||||
response = GetResponse(CurrentRequest, application);
|
// response = GetResponse(CurrentRequest, application);
|
||||||
}
|
// }
|
||||||
catch (Exception e)
|
// catch (Exception e)
|
||||||
{
|
// {
|
||||||
setState("handling exception");
|
// setState("handling exception");
|
||||||
|
|
||||||
response = new HttpResponse(CurrentRequest, "text/plain");
|
// response = new HttpResponse(CurrentRequest, "text/plain");
|
||||||
response.StatusCode = 500;
|
// response.StatusCode = 500;
|
||||||
response.ContentWriter.WriteLine("Exception caught: {0}", e);
|
// response.ContentWriter.WriteLine("Exception caught: {0}", e);
|
||||||
}
|
// }
|
||||||
|
|
||||||
setState("sending response");
|
// setState("sending response");
|
||||||
|
|
||||||
if (response == null)
|
// if (response == null)
|
||||||
{
|
// {
|
||||||
Logging.Log(LogLevel.DEBUG, "Request {0} returned no Response", CurrentRequest);
|
// Logging.Log(LogLevel.DEBUG, "Request {0} returned no Response", CurrentRequest);
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
if (!response.HasCustomContentStream)
|
// if (!response.HasCustomContentStream)
|
||||||
{
|
// {
|
||||||
response.ContentWriter.Flush();
|
// response.ContentWriter.Flush();
|
||||||
MemoryStream cstream = (MemoryStream)response.ContentStream;
|
// MemoryStream cstream = (MemoryStream)response.ContentStream;
|
||||||
cstream.Position = 0;
|
// cstream.Position = 0;
|
||||||
|
|
||||||
response.SetHeader("content-length", cstream.Length.ToString());
|
// response.SetHeader("content-length", cstream.Length.ToString());
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (CurrentRequest.Session != null)
|
// if (CurrentRequest.Session != null)
|
||||||
HTTPServer?.SessionCache?.ApplySessionID(response, CurrentRequest.Session);
|
// HTTPServer?.SessionCache?.ApplySessionID(response, CurrentRequest.Session);
|
||||||
|
|
||||||
response.AddCookie("LN_SEEN", DateTime.Now.ToString());
|
// response.AddCookie("LN_SEEN", DateTime.Now.ToString());
|
||||||
|
|
||||||
SendResponse(TcpClient.GetStream(), response);
|
// SendResponse(TcpClient.GetStream(), response);
|
||||||
TcpClient.Close();
|
// TcpClient.Close();
|
||||||
|
|
||||||
Finished = DateTime.Now;
|
// Finished = DateTime.Now;
|
||||||
|
|
||||||
HTTPServer.Log(Created, (Finished - Created).TotalMilliseconds, CurrentRequest, response);
|
// HTTPServer.Log(Created, (Finished - Created).TotalMilliseconds, CurrentRequest, response);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
Current.Value = saveCurrent;
|
// Current.Value = saveCurrent;
|
||||||
lock (currentConnections)
|
// lock (currentConnections)
|
||||||
currentConnections.Remove(this);
|
// currentConnections.Remove(this);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void SendResponse(Stream stream, HttpResponse response)
|
// public static void SendResponse(Stream stream, HttpResponse response)
|
||||||
{
|
// {
|
||||||
StreamWriter streamWriter = new StreamWriter(stream);
|
// StreamWriter streamWriter = new StreamWriter(stream);
|
||||||
streamWriter.NewLine = "\r\n";
|
// streamWriter.NewLine = "\r\n";
|
||||||
|
|
||||||
streamWriter.WriteLine("{0} {1} {2}", response.HttpRequest.Protocol, response.StatusCode, response.StatusMessage);
|
// streamWriter.WriteLine("{0} {1} {2}", response.HttpRequest.Protocol, response.StatusCode, response.StatusMessage);
|
||||||
foreach (String headerName in response.GetHeaderNames())
|
// foreach (String headerName in response.GetHeaderNames())
|
||||||
{
|
// {
|
||||||
streamWriter.WriteLine("{0}: {1}", headerName, response.GetHeader(headerName));
|
// streamWriter.WriteLine("{0}: {1}", headerName, response.GetHeader(headerName));
|
||||||
}
|
// }
|
||||||
|
|
||||||
foreach (HttpCookie httpCookie in response.Cookies)
|
// foreach (HttpCookie httpCookie in response.Cookies)
|
||||||
{
|
// {
|
||||||
streamWriter.WriteLine("Set-Cookie: {0}", httpCookie.ToString());
|
// streamWriter.WriteLine("Set-Cookie: {0}", httpCookie.ToString());
|
||||||
}
|
// }
|
||||||
|
|
||||||
streamWriter.WriteLine();
|
// streamWriter.WriteLine();
|
||||||
streamWriter.Flush();
|
// streamWriter.Flush();
|
||||||
|
|
||||||
response.ContentStream.CopyTo(stream);
|
// response.ContentStream.CopyTo(stream);
|
||||||
response.ContentStream.Close();
|
// response.ContentStream.Close();
|
||||||
response.ContentStream.Dispose();
|
// response.ContentStream.Dispose();
|
||||||
|
|
||||||
streamWriter.Flush();
|
// streamWriter.Flush();
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
using System;
|
|
||||||
namespace ln.http
|
|
||||||
{
|
|
||||||
public abstract class HttpApplication
|
|
||||||
{
|
|
||||||
public AuthenticationProvider AuthenticationProvider { get; protected set; }
|
|
||||||
|
|
||||||
public HttpApplication()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract HttpResponse GetResponse(HttpRequest httpRequest);
|
|
||||||
|
|
||||||
public virtual void Authenticate(HttpRequest httpRequest) { }
|
|
||||||
public virtual void Authorize(HttpRequest httpRequest) { }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,7 +34,7 @@ namespace ln.http
|
||||||
|
|
||||||
public QueryStringParameters Query { get; private set; }
|
public QueryStringParameters Query { get; private set; }
|
||||||
|
|
||||||
public Session Session => HTTPServer.SessionCache.GetSession(this);
|
public Session Session { get; set; }
|
||||||
public HttpUser CurrentUser => Session.CurrentUser;
|
public HttpUser CurrentUser => Session.CurrentUser;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using ln.logging;
|
||||||
|
namespace ln.http
|
||||||
|
{
|
||||||
|
public abstract class HttpRouter
|
||||||
|
{
|
||||||
|
public HttpRouter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract IHTTPResource FindResource(HttpRequest httpRequest);
|
||||||
|
|
||||||
|
public virtual HttpResponse Route(HttpRequest httpRequest)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IHTTPResource resource = FindResource(httpRequest);
|
||||||
|
return resource.GetResponse(httpRequest);
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
Logging.Log(e);
|
||||||
|
if (httpRequest != null)
|
||||||
|
{
|
||||||
|
HttpResponse httpResponse = new HttpResponse(httpRequest);
|
||||||
|
httpResponse.StatusCode = 500;
|
||||||
|
httpResponse.ContentWriter.WriteLine("500 Internal Server Error");
|
||||||
|
|
||||||
|
return httpResponse;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
using System;
|
||||||
|
namespace ln.http
|
||||||
|
{
|
||||||
|
public interface IHTTPResource
|
||||||
|
{
|
||||||
|
HttpResponse GetResponse(HttpRequest httpRequest);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,9 +15,9 @@ using ln.logging;
|
||||||
using ln.http.listener;
|
using ln.http.listener;
|
||||||
namespace ln.http.connections
|
namespace ln.http.connections
|
||||||
{
|
{
|
||||||
public abstract class Connection
|
public abstract class Connection : IDisposable
|
||||||
{
|
{
|
||||||
public Listener Listener { get; }
|
public Listener Listener { get; private set; }
|
||||||
|
|
||||||
public abstract IPv6 RemoteHost { get; }
|
public abstract IPv6 RemoteHost { get; }
|
||||||
public abstract int RemotePort { get; }
|
public abstract int RemotePort { get; }
|
||||||
|
@ -47,6 +47,13 @@ namespace ln.http.connections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void Close();
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
Listener = null;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void SendResponse(HttpResponse response) => SendResponse(GetStream(), response);
|
public virtual void SendResponse(HttpResponse response) => SendResponse(GetStream(), response);
|
||||||
|
|
||||||
public static void SendResponse(Stream stream, HttpResponse response)
|
public static void SendResponse(Stream stream, HttpResponse response)
|
||||||
|
@ -70,6 +77,7 @@ namespace ln.http.connections
|
||||||
streamWriter.WriteLine();
|
streamWriter.WriteLine();
|
||||||
streamWriter.Flush();
|
streamWriter.Flush();
|
||||||
|
|
||||||
|
response.ContentStream.Position = 0;
|
||||||
response.ContentStream.CopyTo(stream);
|
response.ContentStream.CopyTo(stream);
|
||||||
response.ContentStream.Close();
|
response.ContentStream.Close();
|
||||||
response.ContentStream.Dispose();
|
response.ContentStream.Dispose();
|
||||||
|
|
|
@ -33,5 +33,10 @@ namespace ln.http.connections
|
||||||
|
|
||||||
public override Stream GetStream() => TcpClient.GetStream();
|
public override Stream GetStream() => TcpClient.GetStream();
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
TcpClient.Close();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,5 +38,10 @@ namespace ln.http.connections
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Stream GetStream() => sslStream;
|
public override Stream GetStream() => sslStream;
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
sslStream.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
<Compile Include="HttpResponse.cs" />
|
<Compile Include="HttpResponse.cs" />
|
||||||
<Compile Include="HttpStatusCodes.cs" />
|
<Compile Include="HttpStatusCodes.cs" />
|
||||||
<Compile Include="QueryStringParameters.cs" />
|
<Compile Include="QueryStringParameters.cs" />
|
||||||
<Compile Include="HttpApplication.cs" />
|
|
||||||
<Compile Include="HttpCookie.cs" />
|
<Compile Include="HttpCookie.cs" />
|
||||||
<Compile Include="session\Session.cs" />
|
<Compile Include="session\Session.cs" />
|
||||||
<Compile Include="session\SessionCache.cs" />
|
<Compile Include="session\SessionCache.cs" />
|
||||||
|
@ -65,6 +64,9 @@
|
||||||
<Compile Include="listener\HttpListener.cs" />
|
<Compile Include="listener\HttpListener.cs" />
|
||||||
<Compile Include="listener\HttpsListener.cs" />
|
<Compile Include="listener\HttpsListener.cs" />
|
||||||
<Compile Include="listener\Listener.cs" />
|
<Compile Include="listener\Listener.cs" />
|
||||||
|
<Compile Include="HttpRouter.cs" />
|
||||||
|
<Compile Include="IHTTPResource.cs" />
|
||||||
|
<Compile Include="router\VirtualHostRouter.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="exceptions\" />
|
<Folder Include="exceptions\" />
|
||||||
|
@ -74,6 +76,7 @@
|
||||||
<Folder Include="connections\" />
|
<Folder Include="connections\" />
|
||||||
<Folder Include="cert\" />
|
<Folder Include="cert\" />
|
||||||
<Folder Include="listener\" />
|
<Folder Include="listener\" />
|
||||||
|
<Folder Include="router\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ln.http.exceptions;
|
||||||
|
using ln.types;
|
||||||
|
namespace ln.http.router
|
||||||
|
{
|
||||||
|
public class VirtualHostRouter : HttpRouter
|
||||||
|
{
|
||||||
|
public HttpRouter DefaultRoute { get; set; }
|
||||||
|
|
||||||
|
Dictionary<string, HttpRouter> virtualHosts = new Dictionary<string, HttpRouter>();
|
||||||
|
|
||||||
|
public VirtualHostRouter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public VirtualHostRouter(HttpRouter defaultRoute)
|
||||||
|
{
|
||||||
|
DefaultRoute = defaultRoute;
|
||||||
|
}
|
||||||
|
public VirtualHostRouter(IEnumerable<KeyValuePair<string, HttpRouter>> routes)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, HttpRouter> route in routes)
|
||||||
|
virtualHosts.Add(route.Key, route.Value);
|
||||||
|
}
|
||||||
|
public VirtualHostRouter(HttpRouter defaultRoute,IEnumerable<KeyValuePair<string, HttpRouter>> routes)
|
||||||
|
:this(routes)
|
||||||
|
{
|
||||||
|
DefaultRoute = defaultRoute;
|
||||||
|
}
|
||||||
|
public VirtualHostRouter(VirtualHostRouter source)
|
||||||
|
: this(source.virtualHosts) { }
|
||||||
|
|
||||||
|
public override IHTTPResource FindResource(HttpRequest httpRequest)
|
||||||
|
{
|
||||||
|
if (virtualHosts.TryGetValue(httpRequest.Hostname, out HttpRouter virtualHost))
|
||||||
|
return virtualHost.FindResource(httpRequest);
|
||||||
|
if (DefaultRoute != null)
|
||||||
|
return DefaultRoute.FindResource(httpRequest);
|
||||||
|
|
||||||
|
throw new HttpException(410, String.Format("Gone. Hostname {0} not found on this server.",httpRequest.Hostname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ using ln.http.exceptions;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using ln.types;
|
using ln.types;
|
||||||
|
using ln.http.connections;
|
||||||
|
|
||||||
namespace ln.http.websocket
|
namespace ln.http.websocket
|
||||||
{
|
{
|
||||||
|
@ -68,7 +69,7 @@ namespace ln.http.websocket
|
||||||
Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(acceptKey)))
|
Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(acceptKey)))
|
||||||
);
|
);
|
||||||
|
|
||||||
HTTPServerConnection.SendResponse(Stream, httpResponse);
|
Connection.SendResponse(Stream, httpResponse);
|
||||||
//HTTPServerConnection.Current.Value.AbortRequested += (connection) => Close();
|
//HTTPServerConnection.Current.Value.AbortRequested += (connection) => Close();
|
||||||
State = WebSocketState.OPEN;
|
State = WebSocketState.OPEN;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue