79 lines
2.6 KiB
C#
79 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;
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|