Exemplo n.º 1
0
        public static void Decode(HttpContext context)
        {
            ParserMode mode = ParserMode.FirstLine;

            var body   = new StringBuilder();
            var reader = new StreamReader(context.Channel.InputStream);

            string line;

            while ((line = reader.ReadLine()) != null)
            {
                switch (mode)
                {
                case ParserMode.FirstLine:
                    reader.SkipWhiteSpace();

                    string[] requestLine = line.Split(new char[] { ' ' }, 3);
                    if (requestLine.Length != 3)
                    {
                        throw new Exception("Expected first line to contain three words in accordance HTTP specification.");
                    }

                    if (!requestLine[2].ToLower().StartsWith("http/"))
                    {
                        throw new Exception($"Status line for requests should end with the HTTP version. Your line ended with { requestLine[2] }.");
                    }

                    context.Request.Method = requestLine[0];
                    context.Request.Path   = requestLine[1];

                    if (requestLine[1].Contains("?"))
                    {
                        var parameters = requestLine[1].Split('?')[1];

                        var parsed = QueryValue.TryParseList(parameters, out ArrayList result);
                        if (parsed)
                        {
                            context.Request.Query = new QueryCollection(result);
                        }
                        else
                        {
                            context.Request.Query = QueryCollection.Empty;
                        }

                        context.Request.Path = requestLine[1].Split('?')[0];
                    }
                    else
                    {
                        context.Request.Path = requestLine[1];
                    }

                    context.Request.Path = requestLine[1].Split('?')[0];

                    if (requestLine.Length >= 3)
                    {
                        context.Request.Protocol = requestLine[2];
                    }
                    else
                    {
                        context.Request.Protocol = HttpProtocol.Http11;
                    }

                    mode = ParserMode.Headers;
                    break;

                case ParserMode.Headers:

                    if (string.IsNullOrEmpty(line))
                    {
                        mode = ParserMode.Body;
                        continue;
                    }

                    int seperatorIndex = line.IndexOf(": ");

                    if (seperatorIndex > 1)
                    {
                        var name  = line.Substring(0, seperatorIndex);
                        var value = line.Substring(seperatorIndex + 1);

                        context.Request.Headers.Add(name, value);
                    }
                    break;

                case ParserMode.Body:

                    // TODO: Improve performace by not reading every body line
                    //Stream req = context.Session.InputStream;
                    //req.Seek(0, System.IO.SeekOrigin.Begin);
                    //string body = new StreamReader(req).ReadToEnd();
                    body.AppendLine(line);

                    break;
                }
            }

            var bytes = Encoding.UTF8.GetBytes(body.ToString());

            if (bytes.Length > 0)
            {
                context.Request.Body          = new MemoryStream(bytes);
                context.Request.Body.Position = 0;
            }

            var cookieParser = new HttpCookieParser();
            var cookies      = context.Request.Headers.Cookie;

            if (cookies != null)
            {
                context.Request.Cookies = cookieParser.Parse(cookies);
            }
        }