185 lines
5.4 KiB
C#
185 lines
5.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace AsyncHttp
|
|
{
|
|
public class Server
|
|
{
|
|
private object stop_lock = new object();
|
|
private bool stop = false;
|
|
private HttpListener listener = new HttpListener();
|
|
private List<IPath> paths = new List<IPath>();
|
|
|
|
public int Port
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
public string CertificatePath
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
public string CertificatePassword
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
public int SSLPort
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
public Server(int Port = 8500, int SSLPort = 8443)
|
|
{
|
|
this.Port = Port;
|
|
this.SSLPort = SSLPort;
|
|
}
|
|
|
|
public async Task StartAsync()
|
|
{
|
|
listener.Prefixes.Add("http://*:" + Port.ToString() + "/");
|
|
|
|
if (!string.IsNullOrEmpty(CertificatePath))
|
|
{
|
|
try
|
|
{
|
|
var cert_path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CertificatePath);
|
|
X509Certificate2 cert = new X509Certificate2(cert_path, CertificatePassword);
|
|
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
|
|
store.Open(OpenFlags.ReadWrite);
|
|
if (!store.Certificates.Contains(cert))
|
|
{
|
|
store.Add(cert);
|
|
}
|
|
store.Close();
|
|
listener.Prefixes.Add("https://*:" + SSLPort.ToString() + "/");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// notify in console
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
var paths = from a in AppDomain.CurrentDomain.GetAssemblies()
|
|
from t in a.GetTypes()
|
|
let attributes = t.GetCustomAttributes(typeof(ServerPath), true)
|
|
where attributes != null && attributes.Length > 0
|
|
select new { Type = t, Attributes = attributes.Cast<ServerPath>() };
|
|
|
|
foreach (var t in paths)
|
|
{
|
|
if (t.Type.BaseType == typeof(IPath))
|
|
{
|
|
var obj = (IPath)Activator.CreateInstance(t.Type);
|
|
this.paths.Add(obj);
|
|
}
|
|
}
|
|
|
|
listener.Start();
|
|
stop = false;
|
|
|
|
while (listener.IsListening)
|
|
{
|
|
var context = await listener.GetContextAsync();
|
|
|
|
try
|
|
{
|
|
Console.WriteLine(context.Request.RawUrl);
|
|
await ProcessRequestAsync(context);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("# EXCEPTION # " + ex.StackTrace);
|
|
}
|
|
|
|
lock (stop_lock)
|
|
{
|
|
if ((bool)stop == true) listener.Stop();
|
|
}
|
|
}
|
|
|
|
listener.Close();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.ToString());
|
|
}
|
|
}
|
|
|
|
public IPath GetPathForUrl(HttpListenerContext context)
|
|
{
|
|
for (var i = 0; i < paths.Count; i++)
|
|
{
|
|
var current_path = paths[i];
|
|
if (context.Request.RawUrl == current_path.GetPathString())
|
|
{
|
|
if (current_path.GetMethodString() != "ALL")
|
|
{
|
|
if (context.Request.HttpMethod == current_path.GetMethodString())
|
|
{
|
|
return paths[i];
|
|
}
|
|
}
|
|
else
|
|
return paths[i];
|
|
}
|
|
}
|
|
|
|
return new NotFoundPath();
|
|
}
|
|
|
|
private async Task ProcessRequestAsync(HttpListenerContext context)
|
|
{
|
|
Request req = new Request(context.Request);
|
|
|
|
IPath path = GetPathForUrl(context);
|
|
|
|
path.HandleRequest(req);
|
|
|
|
var Response = path.Response;
|
|
context.Response.StatusCode = Response.Code == 0 ? 200 : Response.Code;
|
|
|
|
var output_stream = context.Response.OutputStream;
|
|
|
|
context.Response.ContentType = (!string.IsNullOrEmpty(Response.ContentType) ?
|
|
Response.ContentType: MimeTypes.Text.Plain);
|
|
|
|
context.Response.Cookies = Response.Cookies;
|
|
|
|
if (Response.Body != null)
|
|
{
|
|
context.Response.ContentLength64 = Response.Body.Length;
|
|
await output_stream.WriteAsync(Response.Body, 0, Response.Body.Length);
|
|
}
|
|
context.Response.Close();
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
lock (stop_lock)
|
|
{
|
|
stop = true;
|
|
}
|
|
}
|
|
|
|
public bool isRunning()
|
|
{
|
|
bool ret_val;
|
|
lock (stop_lock)
|
|
{
|
|
ret_val = !stop;
|
|
}
|
|
return ret_val;
|
|
}
|
|
}
|
|
}
|