Example #1
0
        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}");
        }