using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Web;
|
|
using System.Windows.Forms;
|
|
|
|
namespace AppTime
|
|
{
|
|
class WebServer
|
|
{
|
|
HttpListener listener;
|
|
Thread thread;
|
|
//public HttpListenerRequest Request;
|
|
//public HttpListenerResponse Response;
|
|
public string WebRootPath;
|
|
HashSet<string> defaultPage = new HashSet<string>(StringComparer.OrdinalIgnoreCase){
|
|
"index.html",
|
|
"index.htm",
|
|
"default.html",
|
|
"default.htm"
|
|
};
|
|
|
|
public void Start(int port, object controller, string webfolder = "web")
|
|
{
|
|
thread = new Thread(() =>
|
|
{
|
|
WebRootPath = webfolder = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), webfolder);
|
|
var folders = Directory.GetDirectories(webfolder, "*", SearchOption.AllDirectories);
|
|
|
|
var webroot = $@"http://localhost:{port}/";
|
|
|
|
|
|
listener = new HttpListener();
|
|
foreach (var f in folders)
|
|
{
|
|
listener.Prefixes.Add(webroot + f.Substring(webfolder.Length + 1).Replace("\\", "/") + "/");
|
|
}
|
|
listener.Prefixes.Add(webroot);
|
|
listener.Start();
|
|
|
|
while (true)
|
|
{
|
|
var ctx = listener.GetContext();
|
|
//Debug.WriteLine($"Web Request:{ctx.Request.Url}");
|
|
//ThreadPool.QueueUserWorkItem(_ => processRequest(ctx, webfolder, controller));
|
|
new Thread(() => processRequest(
|
|
ctx,
|
|
webfolder,
|
|
controller)
|
|
)
|
|
{ IsBackground = true, Name = "WebServer Process Request" }.Start();
|
|
}
|
|
})
|
|
{
|
|
Name = "WebServer",
|
|
IsBackground = true
|
|
};
|
|
thread.Start();
|
|
}
|
|
|
|
|
|
void processRequest(HttpListenerContext context, string webfolder, object controller)
|
|
{
|
|
var request = context.Request;
|
|
var file = webfolder + request.RawUrl.Replace("/", "\\");
|
|
string query = "";
|
|
var p = file.IndexOf("?");
|
|
if (p > 0)
|
|
{
|
|
query = file.Substring(p + 1);
|
|
file = file.Substring(0, p);
|
|
}
|
|
var response = context.Response;
|
|
byte[] data = null;
|
|
|
|
|
|
if (Path.GetFileName(Path.GetDirectoryName(file)).Equals("data", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(query))
|
|
{
|
|
using var reader = new StreamReader(request.InputStream);
|
|
query = reader.ReadToEnd();
|
|
}
|
|
var info = JObject.Parse(HttpUtility.UrlDecode(query));
|
|
var method = controller.GetType().GetMethod(Path.GetFileName(file));
|
|
var args = info.Value<JArray>("args").Cast<object>().ToArray();
|
|
var @params = method.GetParameters();
|
|
for (var i = 0; i < args.Length; i++)
|
|
{
|
|
if (args[i] is JObject jo)
|
|
{
|
|
args[i] = jo.ToObject(@params[i].ParameterType);
|
|
}
|
|
else
|
|
{
|
|
args[i] = Convert.ChangeType(args[i], @params[i].ParameterType);
|
|
}
|
|
}
|
|
|
|
var result = method.Invoke(controller, args);
|
|
if (result is byte[] bytes)
|
|
{
|
|
data = bytes;
|
|
}
|
|
else
|
|
{
|
|
data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(result));
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
data = Encoding.UTF8.GetBytes($"bad request: method:{Path.GetFileName(file)} query:{query}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Directory.Exists(file))
|
|
{
|
|
var def = Directory.GetFiles(file).FirstOrDefault(f => defaultPage.Contains(Path.GetFileName(f), StringComparer.OrdinalIgnoreCase));
|
|
if (def != null)
|
|
{
|
|
file = def;
|
|
}
|
|
}
|
|
|
|
if (File.Exists(file))
|
|
{
|
|
var mime = MimeMapping.GetMimeMapping(file);
|
|
response.Headers.Add("Content-type", mime);
|
|
if (mime.StartsWith("text/"))
|
|
{
|
|
response.ContentEncoding = Encoding.GetEncoding("utf-8");
|
|
data = Encoding.UTF8.GetBytes(File.ReadAllText(file, Encoding.Default));
|
|
}
|
|
else
|
|
{
|
|
data = File.ReadAllBytes(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (data == null)
|
|
{
|
|
data = Encoding.UTF8.GetBytes($"file not found: {file}");
|
|
}
|
|
|
|
response.ContentLength64 = data.Length;
|
|
|
|
var output = response.OutputStream;
|
|
try
|
|
{
|
|
output.Write(data, 0, data.Length);
|
|
}
|
|
catch (HttpListenerException ex)
|
|
{
|
|
|
|
}
|
|
output.Close();
|
|
}
|
|
|
|
|
|
public void Stop()
|
|
{
|
|
thread.Abort();
|
|
listener.Stop();
|
|
listener.Close();
|
|
}
|
|
}
|
|
}
|