Tranga-Website/Tranga/API/Server.cs

93 lines
3.2 KiB
C#

using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Logging;
using Newtonsoft.Json;
using Tranga;
namespace Tranga.API;
public class Server
{
private readonly HttpListener _listener = new ();
private readonly RequestHandler _requestHandler;
private readonly TaskManager _taskManager;
internal readonly Logger? logger;
private readonly Regex _validUrl =
new (@"https?:\/\/(www\.)?[-A-z0-9]{1,256}(\.[-a-zA-Z0-9]{1,6})?(:[0-9]{1,5})?(\/{1}[A-z0-9()@:%_\+.~#?&=]+)*\/?");
public Server(int port, TaskManager taskManager, Logger? logger = null)
{
this.logger = logger;
this._taskManager = taskManager;
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
this._listener.Prefixes.Add($"http://*:{port}/");
else
this._listener.Prefixes.Add($"http://localhost:{port}/");
this._requestHandler = new RequestHandler(taskManager, this);
Thread listenThread = new Thread(Listen);
listenThread.Start();
}
private void Listen()
{
this._listener.Start();
foreach (string prefix in this._listener.Prefixes)
this.logger?.WriteLine(this.GetType().ToString(), $"Listening on {prefix}");
while (this._listener.IsListening && _taskManager._continueRunning)
{
HttpListenerContext context = this._listener.GetContextAsync().Result;
Task t = new (() =>
{
HandleContext(context);
});
t.Start();
}
}
private void HandleContext(HttpListenerContext context)
{
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
//logger?.WriteLine(this.GetType().ToString(), $"New request: {request.HttpMethod} {request.Url}");
if (!_validUrl.IsMatch(request.Url!.ToString()))
{
SendResponse(HttpStatusCode.BadRequest, response);
return;
}
if (request.HttpMethod == "OPTIONS")
{
SendResponse(HttpStatusCode.OK, response);
}
else
{
_requestHandler.HandleRequest(request, response);
}
}
internal void SendResponse(HttpStatusCode statusCode, HttpListenerResponse response, object? content = null)
{
//logger?.WriteLine(this.GetType().ToString(), $"Sending response: {statusCode}");
response.StatusCode = (int)statusCode;
response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
response.AddHeader("Access-Control-Allow-Methods", "GET, POST, DELETE");
response.AddHeader("Access-Control-Max-Age", "1728000");
response.AppendHeader("Access-Control-Allow-Origin", "*");
response.ContentType = "application/json";
try
{
response.OutputStream.Write(content is not null
? Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(content))
: Array.Empty<byte>());
}
catch (HttpListenerException)
{
}
response.OutputStream.Close();
}
}