static void handleRequest(APIContext context) { context.Id = Guid.NewGuid(); if (context == null) { Program.LogMsg("context is null"); } if (context.Request == null) { Program.LogMsg("context.Request is null"); } if (context.Request.RemoteEndPoint == null) { Program.LogMsg("context.Request.RemoteEndPoint is null"); } Console.WriteLine($"{(context?.Id.ToString() ?? "null")}: {(context.Request?.RemoteEndPoint?.ToString() ?? "null")} {(context?.Request?.Url.ToString() ?? "null")}"); var idSplit = context.Id.ToString().Split('-'); var logger = new RequestLogger(context); Func <ErrorJson, int, string> sendError = (ErrorJson reply, int code) => { var str = Newtonsoft.Json.JsonConvert.SerializeObject(reply, Newtonsoft.Json.Formatting.None); logger.End((HttpStatusCode)code, str); if (context.WantsHTML) { str = reply.GetPrettyPage(context); } else if (!context.WantsJson) { str = reply.GetSimpleText(); } var bytes = System.Text.Encoding.UTF8.GetBytes(str); context.HTTP.Response.StatusCode = code; context.HTTP.Response.Close(bytes, true); return(""); }; if (!(context.Path.Contains("/_/") || context.Path.StartsWith("/api/tracker/"))) { logger.Write(); } List <APIEndpoint> endpoints; if (!Endpoints.TryGetValue(context.Method, out endpoints)) { logger.End((HttpStatusCode)400, $"Method unrecognised ({context.Method})"); sendError(new ErrorJson("Method is not recognised"), 400); return; } var seeker = new CommandFinder(context, endpoints); if (!seeker.Search()) { var list = new List <ErrorItem>(); var mustRedirectTo = new List <string>(); foreach (var er in seeker.Errors) { var redirects = er.Exceptions.Where(x => x is RedirectException).Select(x => x as RedirectException); foreach (var thing in redirects) { if (!mustRedirectTo.Contains(thing.URL)) { mustRedirectTo.Add(thing.URL); } } list.Add(new ErrorItem(er.Command, er.ErrorReason)); } if (mustRedirectTo.Count == 1) { // every error is solely about not being logged in redirect(logger, context, mustRedirectTo[0]); return; } sendError(new ErrorJson(list), 400); return; } var found = seeker.BestFind; var commandBase = found.CommandBase; var exceptions = found.Exceptions; var failures = exceptions.Where(x => x.CompleteFailure).ToList(); if (failures.Count > 0) { commandBase.RespondRaw($"{string.Join(", ", failures.ToString())}", 500); return; } var redirectEx = exceptions.FirstOrDefault(x => x is RedirectException) as RedirectException; if (redirectEx != null) { redirect(logger, context, redirectEx.URL); return; } commandBase.Context.Endpoint = found.Command; try { commandBase.BeforeExecute(); } catch (RedirectException ex) { redirect(logger, context, ex.URL); logger.End(HttpStatusCode.TemporaryRedirect, ex.Message); return; } catch (ReqHandledException ex) { logger.End((HttpStatusCode)commandBase.StatusSent); return; } catch (HaltExecutionException ex) { Program.LogMsg(ex, $"{context.Id}"); commandBase.ResponseHalted(ex); logger.End(HttpStatusCode.InternalServerError, ex.Message); return; } try { found.Command.Function.Invoke(commandBase, found.Arguments.ToArray()); logger.End((HttpStatusCode)commandBase.StatusSent); } catch (TargetInvocationException outer) { Exception ex = outer.InnerException; try { sendError(new ErrorJson(ex.Message), 500); } catch { } Program.LogMsg(ex, "Handler"); } catch (Exception ex) { try { sendError(new ErrorJson(ex.Message), 500); } catch { } Program.LogMsg(ex, "ExHandler"); } commandBase.AfterExecute(); Console.WriteLine($"{context.Id}: Returned {commandBase.StatusSent}"); }