add ParsedParameters to RequestContext, cleanup error handling
This commit is contained in:
parent
8cdff9268a
commit
6cc849bf01
|
|
@ -213,11 +213,11 @@ public sealed class HttpServer {
|
|||
foreach (var queryKV in queryStringArgs) {
|
||||
var queryKVSplitted = queryKV.Split('=');
|
||||
if (queryKVSplitted.Length != 2) {
|
||||
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.BadRequest, "Malformed request URL parameters");
|
||||
await HandleDefaultErrorPageAsync(rc, HttpStatusCode.BadRequest, "Malformed request URL parameters");
|
||||
return;
|
||||
}
|
||||
if (!parsedQParams.TryAdd(WebUtility.UrlDecode(queryKVSplitted[0]), WebUtility.UrlDecode(queryKVSplitted[1]))) {
|
||||
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.BadRequest, "Duplicate request URL parameters");
|
||||
await HandleDefaultErrorPageAsync(rc, HttpStatusCode.BadRequest, "Duplicate request URL parameters");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -230,20 +230,21 @@ public sealed class HttpServer {
|
|||
if (stringToTypeParameterConverters[qparamInfo.type].TryConvertFromString(qparamValue, out object objRes)) {
|
||||
convertedQParamValues[i] = objRes;
|
||||
} else {
|
||||
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.BadRequest);
|
||||
await HandleDefaultErrorPageAsync(rc, HttpStatusCode.BadRequest);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (qparamInfo.isOptional) {
|
||||
convertedQParamValues[i] = null!;
|
||||
} else {
|
||||
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.BadRequest, $"Missing required query parameter {qparamName}");
|
||||
await HandleDefaultErrorPageAsync(rc, HttpStatusCode.BadRequest, $"Missing required query parameter {qparamName}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
convertedQParamValues[0] = rc;
|
||||
rc.ParsedParameters = parsedQParams.AsReadOnly();
|
||||
|
||||
await (Task) (mi.Invoke(null, convertedQParamValues) ?? throw new NullReferenceException("Website func returned null unexpectedly"));
|
||||
} else {
|
||||
|
|
@ -256,7 +257,7 @@ public sealed class HttpServer {
|
|||
|
||||
if (Path.GetRelativePath(v, staticResponsePath).Contains("..")) {
|
||||
requestLogger.Warning($"Blocked GET request to {reqPath} as somehow the target file does not lie inside the static serve folder? Are you using symlinks?");
|
||||
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.NotFound);
|
||||
await HandleDefaultErrorPageAsync(rc, HttpStatusCode.NotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +266,7 @@ public sealed class HttpServer {
|
|||
using var f = File.OpenRead(staticResponsePath);
|
||||
await f.CopyToAsync(rc.ListenerContext.Response.OutputStream);
|
||||
} else {
|
||||
await rc.SetStatusCodeAndDisposeAsync(HttpStatusCode.NotFound);
|
||||
await HandleDefaultErrorPageAsync(rc, HttpStatusCode.NotFound);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -281,19 +282,27 @@ public sealed class HttpServer {
|
|||
} finally {
|
||||
try { await rc.RespWriter.FlushAsync(); } catch (ObjectDisposedException) { }
|
||||
rc.ListenerContext.Response.Close();
|
||||
}
|
||||
|
||||
LogRequest();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task HandleDefaultErrorPageAsync(RequestContext ctx, HttpStatusCode errorCode, string? statusDescription = null) => await HandleDefaultErrorPageAsync(ctx, (int) errorCode, statusDescription);
|
||||
|
||||
private static async Task HandleDefaultErrorPageAsync(RequestContext ctx, int errorCode) {
|
||||
private static async Task HandleDefaultErrorPageAsync(RequestContext ctx, int errorCode, string? statusDescription = null) {
|
||||
ctx.SetStatusCode(errorCode);
|
||||
string desc = statusDescription != null ? $"\r\n{statusDescription}" : "";
|
||||
await ctx.WriteLineToRespAsync($"""
|
||||
<body>
|
||||
<h1>Oh no, an error occurred!</h1>
|
||||
<p>Code: {errorCode}</p>
|
||||
<p>Code: {errorCode}</p>{desc}
|
||||
</body>
|
||||
""");
|
||||
try {
|
||||
if (statusDescription == null) {
|
||||
await ctx.SetStatusCodeAndDisposeAsync(errorCode);
|
||||
} else {
|
||||
await ctx.SetStatusCodeAndDisposeAsync(errorCode, statusDescription);
|
||||
}
|
||||
} catch (ObjectDisposedException) { }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
using System.Net;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Net;
|
||||
|
||||
namespace SimpleHttpServer;
|
||||
public class RequestContext : IDisposable {
|
||||
|
||||
public HttpListenerContext ListenerContext { get; }
|
||||
public ReadOnlyDictionary<string, string> ParsedParameters { get; internal set; }
|
||||
|
||||
private StreamReader? reqReader;
|
||||
public StreamReader ReqReader => reqReader ??= new(ListenerContext.Request.InputStream);
|
||||
|
|
@ -29,6 +31,7 @@ public class RequestContext : IDisposable {
|
|||
using (this) {
|
||||
SetStatusCode(status);
|
||||
await WriteToRespAsync("\n\n");
|
||||
await RespWriter.FlushAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +39,7 @@ public class RequestContext : IDisposable {
|
|||
using (this) {
|
||||
SetStatusCode((int) status);
|
||||
await WriteToRespAsync("\n\n");
|
||||
await RespWriter.FlushAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,11 +49,17 @@ public class RequestContext : IDisposable {
|
|||
ListenerContext.Response.StatusCode = status;
|
||||
ListenerContext.Response.StatusDescription = description;
|
||||
await WriteToRespAsync("\n\n");
|
||||
await RespWriter.FlushAsync();
|
||||
}
|
||||
}
|
||||
public async Task SetStatusCodeAndDisposeAsync(HttpStatusCode status, string description) => await SetStatusCodeAndDisposeAsync((int) status, description);
|
||||
|
||||
|
||||
public async Task WriteRedirect302AndDisposeAsync(string url) {
|
||||
ListenerContext.Response.AddHeader("Location", url);
|
||||
await SetStatusCodeAndDisposeAsync(HttpStatusCode.Redirect);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose() {
|
||||
reqReader?.Dispose();
|
||||
respWriter?.Dispose();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user