public IHttpResponse HandleRequest(IHttpRequest request, TokenState tokenState)
        {
            _logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "GetRequestHandler started"));

            Stopwatch        timer   = Stopwatch.StartNew();
            IActivityHandler handler = GetRequestHandler(request);

            var handlerName = handler != null?handler.GetType().Name : "null";

            _logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "GetRequestHandler completed"),
                          new LogItem("DurationMilliseconds", timer.Elapsed.TotalMilliseconds),
                          new LogItem("FoundHandler", handlerName));

            if (handler == null)
            {
                return(null);
            }

            IHttpResponse response = _container.GetInstance <IHttpResponse>(true);

            _logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "Handler Handle called"));
            timer.Restart();

            handler.Handle(request, response);
            _logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "Handler Handle completed"), new LogItem("DurationMilliseconds", timer.Elapsed.TotalMilliseconds));

            return(response);
        }
        public void Handle(IHttpRequest request, IHttpResponse response)
        {
            Dictionary <Type, ActivityHandlerAttribute[]> handlers = _container.GetAttributedTypes <ActivityHandlerAttribute>(typeof(IActivityHandler));
            List <object> handlerInfoList = new List <object>();

            foreach (KeyValuePair <Type, ActivityHandlerAttribute[]> keyValuePair in handlers)
            {
                foreach (ActivityHandlerAttribute attribute in keyValuePair.Value)
                {
                    var instance = (IActivityHandler)_container.GetInstance(keyValuePair.Key);
                    handlerInfoList.Add(new
                    {
                        path               = attribute.Path,
                        verb               = attribute.Verb.ToString(),
                        description        = attribute.Description,
                        expectedParameters = attribute.ExpectedParameters,
                        exampleCall        =
                            $"{attribute.Path}{(attribute.ExpectedParameters.Any() ? "?" : "")}{string.Join("&", attribute.ExpectedParameters.Select(a => a + "=<value>"))}",
                        exampleRequestDocument  = instance.ExampleRequestDocument,
                        exampleResponseDocument = instance.ExampleResponseDocument,
                    });
                }
            }
            response.SetObjectContent(handlerInfoList);
        }
示例#3
0
        public IHttpResponse HandleRequest(IHttpRequest request, TokenState tokenState)
        {
            IHttpResponse response = _container.GetInstance <IHttpResponse>(true);

            if (tokenState == TokenState.Invalid || tokenState == TokenState.Expired || tokenState == TokenState.NotYetValid)
            {
                return(UnauthorisedResponse);
            }

            logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "GetRequestHandler started"));
            Stopwatch timer = Stopwatch.StartNew();

            IActivityHandler handler = GetRequestHandler(request, out ActivityHandlerAttribute attribute);

            var handlerName = handler != null?handler.GetType().Name : "null";

            logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "GetRequestHandler completed"), new LogItem("DurationMilliseconds", timer.Elapsed.TotalMilliseconds), new LogItem("FoundHandler", handlerName));

            if (handler == null)
            {
                switch (request.Verb)
                {
                case HttpVerb.Options:
                    handler   = _container.GetInstance <OptionsActivityHandler>();
                    attribute = new ActivityHandlerAttribute("", request.Verb, "")
                    {
                        SkipAuthorisation = true
                    };
                    break;

                default:
                    return(null);
                }
            }

            JwtSecurityToken token = request.SecurityToken;

            if (!activityAuthorisationManager.CheckAuthorisation(token, attribute))
            {
                var unauthorised = _container.GetInstance <IHttpResponse>(true);
                unauthorised.HttpStatusCode = HttpStatusCode.Unauthorized;
                return(unauthorised);
            }

            logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "Handler Handle called"));
            timer.Restart();

            try
            {
                handler.Handle(request, response);
            }
            catch (Exception exception)
            {
                logger.Exception($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", "Exception caught handling request", exception);

                response.SetStringContent(string.Empty);
                response.HttpStatusCode = HttpStatusCode.InternalServerError;
            }

            var elapsedMilliseconds = timer.Elapsed.TotalMilliseconds;

            logger.Trace($"{nameof(RequestBroker)}.{nameof(HandleRequest)}", new LogItem("Event", "Handler Handle completed"), new LogItem("DurationMilliseconds", elapsedMilliseconds));
            apiMetrics.RecordHandlerDuration(elapsedMilliseconds, handlerName, response.HttpStatusCode);

            return(response);
        }
示例#4
0
        private void Processor(Socket s)
        {
            try
            {
                byte[]      buffer        = new byte[4096];
                byte[]      content       = null;
                int         contentOffset = 0;
                HttpRequest request       = null;

                Stopwatch connectionTimer = Stopwatch.StartNew();

                using (NetworkStream ns = new NetworkStream(s))
                {
                    while (true)
                    {
                        int bytesReceived;
                        do
                        {
                            bytesReceived = ns.Read(buffer, 0, buffer.Length);
                            if (bytesReceived != 0)
                            {
                                break;
                            }
                            Thread.Sleep(1);
                        } while (connectionTimer.ElapsedMilliseconds < requestTimeout);

                        if (bytesReceived == 0)
                        {
                            s.Shutdown(SocketShutdown.Both);
                            s.Dispose();
                            ns.Dispose();
                            logger.Trace($"{nameof(NanoHttp)}.{nameof(Processor)}", new LogItem("Event", "Closed socket"), new LogItem("Reason", $"No request received in {requestTimeout}ms"));
                            return;
                        }

                        byte[] received = new byte[bytesReceived];
                        Array.Copy(buffer, 0, received, 0, bytesReceived);

                        if (request == null)
                        {
                            int i = received.FindPattern((byte)13, (byte)10, (byte)13, (byte)10);

                            // If we have a double CRLF then we have a complete header, otherwise keep looping
                            if (i == -1)
                            {
                                continue;
                            }

                            request = ParseHeader(i, ref received, ref content, ref contentOffset, ref bytesReceived);

                            if (request == null)
                            {
                                s.Shutdown(SocketShutdown.Both);
                                s.Dispose();
                                ns.Dispose();
                                return;
                            }
                        }

                        Array.Copy(received, 0, content, contentOffset, bytesReceived);
                        contentOffset += bytesReceived;
                        if (contentOffset < content.Length - 1)
                        {
                            continue;
                        }

                        // Completed loading body, which could have urlencoded content :(
                        TokenState tokenState = request.FinaliseLoad(request.Verb != HttpVerb.Options && validJwtRequired, TokenValidationParameters);

                        request.Body = content;
                        logger.Trace($"{nameof(NanoHttp)}.{nameof(Processor)}", new LogItem("Event", "HandleRequest started"));
                        Stopwatch     responseTimer = Stopwatch.StartNew();
                        IHttpResponse response      = null;

                        foreach (IRequestBroker requestBroker in requestBrokers.OrderBy(x => x.Precedence))
                        {
                            response = requestBroker.HandleRequest(request, tokenState);
                            if (response != null)
                            {
                                break;
                            }
                        }

                        if (response == null)
                        {
                            response = container.GetInstance <IHttpResponse>(true);
                            response.HttpStatusCode = HttpStatusCode.NotFound;
                            response.HttpContent    = new NotFoundHttpContent();
                        }

                        logger.Trace($"{nameof(NanoHttp)}.{nameof(Processor)}",
                                     new LogItem("Event", "HandleRequest completed"),
                                     new LogItem("DurationMilliseconds", responseTimer.Elapsed.TotalMilliseconds));

                        response.Headers.Add("Access-Control-Allow-Origin", "*");
                        response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT,OPTIONS");
                        response.Headers.Add("Access-Control-Allow-Headers", "authorization");
                        response.Headers.Add("Connection", "close");

                        if (response.CachingDisabled)
                        {
                            if (!response.Headers.ContainsKey("Expires"))
                            {
                                response.Headers.Add("Expires", "-1");
                            }

                            if (!response.Headers.ContainsKey("Pragma"))
                            {
                                response.Headers.Add("Pragma", "no-cache");
                            }

                            if (!response.Headers.ContainsKey("Cache-Control"))
                            {
                                response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
                            }
                        }

                        response.WriteToStream(ns);

                        ns.Flush();

                        if (response.HttpStatusCode == HttpStatusCode.SwitchingProtocols)
                        {
                            // #######################################
                            // #      WebSocket Stuff Goes Here      #
                            // # https://tools.ietf.org/html/rfc6455 #
                            // #######################################

                            // There's a blocking call here into a message loop

                            // while true ...
                            //   wait for a websocket message
                            //   ... etc
                            // end
                        }

                        s.Shutdown(SocketShutdown.Both);

                        s.Dispose();
                        ns.Dispose();

                        logger.Trace($"{nameof(NanoHttp)}.{nameof(Processor)}",
                                     new LogItem("Event", "Closed socket"),
                                     new LogItem("Reason", "Response complete"),
                                     new LogItem("DurationMilliseconds", connectionTimer.Elapsed.TotalMilliseconds));

                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error($"{nameof(NanoHttp)}.{nameof(Processor)}",
                             new LogItem("Event", "An error occurred processing request"),
                             new LogItem("Exception", ex.ToString));

                throw;
            }
        }