CSharpHttpServer/SimpleHttpServer/HttpEndpointHandler.cs
2023-11-30 17:31:19 +01:00

77 lines
2.6 KiB
C#

using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SimpleHttpServer;
internal class HttpEndpointHandler {
private static readonly DefaultAuthorizer defaultAuth = new();
private readonly IAuthorizer _auth;
private readonly MethodInfo _handler;
private readonly Dictionary<string, (int pindex, Type type, int pparamIdx)> _params;
private readonly Func<Exception, HttpResponseBuilder> _errorPageBuilder;
public HttpEndpointHandler() {
_auth = defaultAuth;
}
public HttpEndpointHandler(IAuthorizer auth) {
}
public virtual void Handle(HttpListenerContext ctx) {
try {
var (isAuth, authData) = _auth.IsAuthenticated(ctx);
if (!isAuth) {
throw new HttpHandlingException(401, "Authorization required!");
}
// collect parameters
var invokeParams = new object?[_params.Count + 1];
var set = new BitArray(_params.Count);
invokeParams[0] = ctx;
// read pparams
// read qparams
var qst = ctx.Request.QueryString;
foreach (var qelem in ctx.Request.QueryString.AllKeys) {
if (_params.ContainsKey(qelem!)) {
var (pindex, type, isPParam) = _params[qelem!];
if (type == typeof(string)) {
invokeParams[pindex] = ctx.Request.QueryString[qelem!];
set.Set(pindex - 1, true);
} else {
var elem = JsonConvert.DeserializeObject(ctx.Request.QueryString[qelem!]!, type);
if (elem != null) {
invokeParams[pindex] = elem;
set.Set(pindex - 1, true);
}
}
}
}
// fill with defaults
foreach (var p in _params) {
if (!set.Get(p.Value.pindex)) {
invokeParams[p.Value.pindex] = p.Value.type.IsValueType ? Activator.CreateInstance(p.Value.type) : null;
}
}
var builder = _handler.Invoke(null, invokeParams) as HttpResponseBuilder;
builder!.SendResponse(ctx.Response);
} catch (Exception e) {
if (e is TargetInvocationException tex) {
e = tex.InnerException!;
}
_errorPageBuilder(e).SendResponse(ctx.Response);
}
}
}