Minimum viable
This commit is contained in:
1 parent
476aff202f
commit
07229424a4
14 files changed
+564
No files matched your search
@@ -0,0 +1,141 @@
|
||||
using CommunityMapLocation.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using UnityModManagerNet;
|
||||
|
||||
namespace CommunityMapLocation.Api
|
||||
{
|
||||
public class ApiServer
|
||||
{
|
||||
public ApiServer(Settings settings, UnityModManager.ModEntry.ModLogger logger)
|
||||
{
|
||||
listener = new HttpListener();
|
||||
|
||||
serializerOptions = new JsonSerializerOptions()
|
||||
{
|
||||
ReferenceHandler = ReferenceHandler.IgnoreCycles,
|
||||
IncludeFields = true,
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
this.settings = settings;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private readonly Settings settings;
|
||||
private readonly UnityModManager.ModEntry.ModLogger logger;
|
||||
|
||||
private readonly HttpListener listener;
|
||||
|
||||
private readonly JsonSerializerOptions serializerOptions;
|
||||
|
||||
private readonly List<IEndpoint> endpoints = new List<IEndpoint>();
|
||||
|
||||
public void AutoRegister(Assembly assembly = null)
|
||||
{
|
||||
if (assembly == null)
|
||||
{
|
||||
assembly = Assembly.GetExecutingAssembly();
|
||||
}
|
||||
|
||||
foreach (var endpointType in assembly.ExportedTypes.Where(t => !t.IsInterface && !t.IsAbstract && typeof(IEndpoint).IsAssignableFrom(t)))
|
||||
{
|
||||
try
|
||||
{
|
||||
endpoints.Add((IEndpoint)Activator.CreateInstance(endpointType));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Warning($"Could not register endpoint {endpointType.Name}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterEndpoint(IEndpoint endpoint)
|
||||
{
|
||||
endpoints.Add(endpoint);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.Prefixes.Add($"http://localhost:{settings.Port}/");
|
||||
listener.Start();
|
||||
listener.BeginGetContext(HandleConnection, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Warning(ex.ToString());
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleConnection(IAsyncResult ar)
|
||||
{
|
||||
try
|
||||
{
|
||||
var context = listener.EndGetContext(ar);
|
||||
|
||||
listener.BeginGetContext(HandleConnection, listener);
|
||||
|
||||
var request = context.Request;
|
||||
var response = context.Response;
|
||||
|
||||
var matchedEndpoints = endpoints.Where(e => e.Matches(request.Url) &&
|
||||
(request.HttpMethod == "OPTIONS" || request.HttpMethod.Equals(e.HttpMethod.ToString(), StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
if (!endpoints.Any())
|
||||
{
|
||||
response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||
}
|
||||
else
|
||||
{
|
||||
var methods = matchedEndpoints.Select(e => e.HttpMethod).Distinct();
|
||||
|
||||
response.AppendHeader("Access-Control-Allow-Origin", settings.RequestSourceType == RequestSourceType.All ? "*" : settings.RequestSource);
|
||||
|
||||
if (request.HttpMethod == "OPTIONS")
|
||||
{
|
||||
response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
|
||||
response.AddHeader("Access-Control-Allow-Methods", String.Join(", ", methods.Select(m => m.ToString().ToUpper())));
|
||||
response.AddHeader("Access-Control-Max-Age", "1728000");
|
||||
}
|
||||
else
|
||||
{
|
||||
var responseBody = matchedEndpoints.First().Handle(logger, request);
|
||||
|
||||
var buffer = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(responseBody, serializerOptions));
|
||||
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
response.OutputStream.Close();
|
||||
}
|
||||
catch (HttpListenerException)
|
||||
{
|
||||
// HttpListener is stopping, swallow exception
|
||||
}
|
||||
}
|
||||
|
||||
internal void Reload()
|
||||
{
|
||||
Stop();
|
||||
Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
listener.Stop();
|
||||
listener.Prefixes.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user