Add static serving

This commit is contained in:
GHXX 2024-01-15 19:56:14 +01:00
parent 8545ed80e9
commit 0814bc6b2d

View File

@ -187,13 +187,18 @@ public sealed class HttpServer {
private async Task ProcessRequestAsync(HttpListenerContext ctx) { private async Task ProcessRequestAsync(HttpListenerContext ctx) {
using RequestContext rc = new RequestContext(ctx); using RequestContext rc = new RequestContext(ctx);
var decUri = WebUtility.UrlDecode(ctx.Request.RawUrl)!; // TODO add path escape countermeasure-unittests
var splitted = decUri.Split('?', 2, StringSplitOptions.None);
var reqPath = NormalizeUrlPath(WebUtility.UrlDecode(splitted.First()));
string requestMethod = ctx.Request.HttpMethod.ToUpperInvariant();
bool wasStaticlyServed = false;
void LogRequest() {
requestLogger.Information($"{rc.ListenerContext.Response.StatusCode} {(wasStaticlyServed ? "static" : "endpnt")} {requestMethod} {decUri}");
}
try { try {
var decUri = WebUtility.UrlDecode(ctx.Request.RawUrl)!; // TODO add path escape countermeasures+unittests
var splitted = decUri.Split('?', 2, StringSplitOptions.None);
var reqPath = NormalizeUrlPath(WebUtility.UrlDecode(splitted.First()));
if (simpleEndpointMethodInfos.TryGetValue((reqPath, requestMethod), out var endpointInvocationInfo)) {
if (simpleEndpointMethodInfos.TryGetValue((reqPath, ctx.Request.HttpMethod.ToUpperInvariant()), out var endpointInvocationInfo)) {
var mi = endpointInvocationInfo.methodInfo; var mi = endpointInvocationInfo.methodInfo;
var qparams = endpointInvocationInfo.queryParameters; var qparams = endpointInvocationInfo.queryParameters;
var args = splitted.Length == 2 ? splitted[1] : null; var args = splitted.Length == 2 ? splitted[1] : null;
@ -242,15 +247,29 @@ public sealed class HttpServer {
await (Task) (mi.Invoke(null, convertedQParamValues) ?? throw new NullReferenceException("Website func returned null unexpectedly")); await (Task) (mi.Invoke(null, convertedQParamValues) ?? throw new NullReferenceException("Website func returned null unexpectedly"));
} else { } else {
if (requestMethod == "GET")
foreach (var (k, v) in staticServePaths) {
if (reqPath.StartsWith(k)) { // do a static serve
wasStaticlyServed = true;
var relativeStaticReqPath = reqPath[k.Length..];
var staticResponsePath = Path.Combine(v, relativeStaticReqPath);
foreach (var (k, v) in staticServePaths) { if (Path.GetRelativePath(v, staticResponsePath).Contains("..")) {
if (k.StartsWith(reqPath)) { // do a static serve requestLogger.Warning($"Blocked GET request to {reqPath} as somehow the target file does not lie inside the static serve folder? Are you using symlinks?");
// TODO finish and add path traversal checking await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.NotFound);
return;
}
if (File.Exists(staticResponsePath)) {
break; rc.SetStatusCode(HttpStatusCode.OK);
using var f = File.OpenRead(v);
await f.CopyToAsync(rc.ListenerContext.Response.OutputStream);
} else {
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.NotFound);
}
return;
}
} }
}
// invoke 404 // invoke 404
await HandleDefaultErrorPageAsync(rc, 404); await HandleDefaultErrorPageAsync(rc, 404);
@ -260,6 +279,8 @@ public sealed class HttpServer {
await HandleDefaultErrorPageAsync(rc, 500); await HandleDefaultErrorPageAsync(rc, 500);
mainLogger.Fatal($"Caught otherwise uncaught exception while ProcessingRequest:\n{ex}"); mainLogger.Fatal($"Caught otherwise uncaught exception while ProcessingRequest:\n{ex}");
} }
LogRequest();
} }