ln.http/ln.http/HttpServer.cs

185 lines
7.3 KiB
C#

using System;
using System.Collections.Generic;
using ln.logging;
using ln.http.exceptions;
using System.IO;
using System.Text;
using System.Threading;
namespace ln.http
{
/*
public class HttpServer
{
public static bool DefaultRouteAuthentication { get; set; } = false;
private HashSet<HttpRouterDelegate> _routerDelegates = new HashSet<HttpRouterDelegate>();
public IEnumerable<HttpRouterDelegate> Routers => _routerDelegates;
public TextWriter AccessLogWriter { get; set; }
private ILogWriter _logWriter;
private HashSet<IHttpAuthenticationSource> _authenticationSources = new HashSet<IHttpAuthenticationSource>();
public IEnumerable<IHttpAuthenticationSource> AuthenticationSources => _authenticationSources;
public HttpServer() : this(Console.Out, new LogWriter(new ConsoleLogSink()))
{
}
public HttpServer(TextWriter accessLogWriter, ILogWriter logWriter)
{
AccessLogWriter = accessLogWriter;
_logWriter = logWriter;
}
public HttpServer(HttpRouterDelegate router)
: this()
{
AddRouter(router);
}
public void RegisterAuthenticationSource(IHttpAuthenticationSource authenticationSource) =>
_authenticationSources.Add(authenticationSource);
public void UnregisterAuthenticationSource(IHttpAuthenticationSource authenticationSource) =>
_authenticationSources.Remove(authenticationSource);
public void AddRouter(HttpRouter httpRouter) => AddRouter(httpRouter.RouteRequest);
public void AddRouter(HttpRouterDelegate routerDelegate) => _routerDelegates.Add(routerDelegate);
public void RemoveRouter(HttpRouter httpRouter) => RemoveRouter(httpRouter.RouteRequest);
public void RemoveRouter(HttpRouterDelegate routerDelegate) => _routerDelegates.Remove(routerDelegate);
public void Connection(HttpConnection httpConnection) =>
ThreadPool.QueueUserWorkItem((state => ConnectionWorker(httpConnection)));
public void ConnectionWorker(HttpConnection httpConnection)
{
try
{
bool keepalive = false;
do
{
DateTime start = DateTime.Now;
using (HttpRequest httpRequest = ReadRequest(httpConnection))
{
if (httpRequest == null)
break;
HttpContext httpContext = new HttpContext(this, httpRequest);
try
{
if (!RouteRequest(httpContext))
throw new HttpException(HttpStatusCode.NotFound);
}
catch (Exception exception)
{
_logWriter?.Log(exception);
if (exception is HttpException httpException)
{
try
{
HttpContext errorContext = new HttpContext(httpContext, httpException);
if (!RouteRequest(errorContext))
{
errorContext.ResetRoutingStack(String.Format("/_err.html",
(int)httpException.HttpStatusCode));
RouteRequest(errorContext);
}
httpContext.Response = errorContext.Response;
}
finally
{
if (httpContext.Response is null)
httpContext.Response = HttpResponse
.InternalServerError()
.Content(
String.Format("An internal error occured ({0})", exception.ToString()));
}
}
else
{
httpContext.Response = HttpResponse.InternalServerError()
.Content(String.Format("An internal error occured ({0})", exception.ToString()));
}
}
try
{
httpContext.Response.WriteTo(httpConnection.ClientStream);
httpContext.Response?.ContentStream?.Dispose();
}
catch (IOException ioexception)
{
break;
}
DateTime end = DateTime.Now;
TimeSpan duration = end - start;
AccessLogWriter?.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}",
start,
end,
duration,
httpConnection.RemoteEndPoint?.ToString(),
httpContext.Response?.StatusCode.ToString() ?? "-",
httpContext.AuthenticatedPrincipal?.ToString() ?? "-",
httpContext.Request.Method,
httpContext.Request.RequestUri
);
AccessLogWriter?.Flush();
keepalive = httpContext.Response.GetHeader("connection", "keep-alive").Equals("keep-alive") &&
httpRequest
.GetRequestHeader("connection",
httpRequest.Protocol.Equals("HTTP/1.1") ? "keep-alive" : "close").Contains(
"keep-alive",
StringComparison.InvariantCultureIgnoreCase);
}
} while (keepalive);
}
finally
{
httpConnection.ClientStream.Close();
httpConnection.ClientStream.Dispose();
}
}
private bool RouteRequest(HttpContext httpContext)
{
foreach (var routerDelegate in _routerDelegates)
{
if (routerDelegate(httpContext))
return true;
}
return false;
}
private HttpRequest ReadRequest(HttpConnection httpConnection)
{
try
{
if (HttpLikeProtocolReader.ReadRequest(httpConnection.ClientStream, Encoding.UTF8, out Request request))
return new HttpRequest(this, request);
return null;
} catch (IOException)
{
return null;
} catch (ConnectionClosedException)
{
return null;
} catch (Exception e)
{
_logWriter?.Log(e);
return null;
}
}
}
*/
}