예제 #1
0
 /// <summary>
 ///     Parses a HTTP header from a HTTP/2 header collection
 /// </summary>
 /// <param name="headers">the header collection including pseudo headers</param>
 /// <param name="methodResolver">the method resolver</param>
 /// <returns>an optional used to determine if the invoker should listen for a payload</returns>
 public static HttpParserOptional ParseFrom(HttpHeaderCollection headers,
                                            MethodResolver <HttpMethod> methodResolver)
 {
     return(new HttpParserOptional
     {
         ExpectPayload = methodResolver.GetMethod(Encoding.UTF8.GetBytes(headers[":method"])).ExpectPayload ||
                         headers.ContainsKey("content-length") && headers["content-length"] != "0",
         Headers = headers,
         MethodResolver = methodResolver,
         Payload = null
     });
 }
예제 #2
0
        /// <summary>
        /// Creates and populates this collection from a <see cref="HttpHeaderCollection"/>, and optionally make it read-only
        /// </summary>
        /// <param name="headers"></param>
        /// <param name="readOnly"></param>
        public HttpCookieCollection(HttpHeaderCollection headers, bool readOnly = false)
        {
            _cookies = new List <HttpCookie>();
            foreach (var headerField in headers)
            {
                if (headerField.Name == "cookie")
                {
                    _cookies.AddRange(HttpCookie.Parse(headerField.Value));
                }
            }

            _readOnly = readOnly;
        }
예제 #3
0
        /// <summary>
        ///     Instantiates with the given <see cref="HttpHeaderCollection" />, payload, and method resolver.
        /// </summary>
        /// <param name="headers">
        ///     a collection of HTTP/2 headers with pseudo headers included (:method, :scheme, :authority, :path,
        ///     and (optionally), :version
        /// </param>
        /// <param name="payload">the request payload (can be null)</param>
        /// <param name="methodResolver">
        ///     a method resolver to use to map the method name to a server-implemented
        ///     <see cref="HttpMethod" />
        /// </param>
        public HttpRequest(HttpHeaderCollection headers, byte[] payload,
                           MethodResolver <HttpMethod> methodResolver)
        {
            if (payload != null)
            {
                InputStream = new MemoryStream(payload);
            }
            Method      = methodResolver.GetMethod(Encoding.UTF8.GetBytes(headers[":method"].ToUpper()));
            RawMethod   = headers[":method"];
            Url         = new Uri(headers[":scheme"] + "://" + headers[":authority"] + headers[":path"]);
            RawUrl      = headers[":path"];
            Headers     = new HttpHeaderCollection(headers.Where <HeaderField>(x => !x.Name.StartsWith(":")));
            InputStream = payload == null ? new MemoryStream() : new MemoryStream(payload);
#pragma warning disable 618
            Protocol = headers.ContainsKey(":version") ? headers[":version"] : null;
#pragma warning restore 618
            Cookies = new HttpCookieCollection(headers, true);
        }
예제 #4
0
        /// <summary>
        ///     Parses a HTTP header from a string
        /// </summary>
        /// <param name="requestHeader">the header to parse</param>
        /// <param name="methodResolver">the method resolver</param>
        /// <param name="connection">
        ///     the connection that the requestHeader was sourced from. Used to determine the scheme
        ///     (http/https)
        /// </param>
        /// <returns>an optional that will determine the next steps of context construction</returns>
        /// <exception cref="BadRequestException">the request was of an invalid structure</exception>
        public static HttpParserOptional ParseFrom(string requestHeader, MethodResolver <HttpMethod> methodResolver,
                                                   IConnection connection)
        {
            var lines = requestHeader.Split(new[] { "\r\n" }, StringSplitOptions.None);

            if (lines.Length < 1)
            {
                throw new BadRequestException("Bad Request (HTTP/1 parser failure)",
                                              new ArgumentException("Request header contains less than one line", nameof(requestHeader)));
            }

            var rparts = lines[0].Split(' ');
            var method = rparts.First();
            var path   = rparts.Where(part => part != rparts[0]).Where(part => part != rparts[rparts.Length - 1])
                         .Aggregate("", (current, part) => current + part + " ").TrimEnd();
            var proto = rparts.Last();

            if (string.IsNullOrEmpty(method) ||
                string.IsNullOrEmpty(path) ||
                string.IsNullOrEmpty(proto))
            {
                throw new BadRequestException("Bad Request (HTTP/1 parser failure)",
                                              new NullReferenceException(
                                                  "The method, path, and/or protocol parameters aren't present in the request line"));
            }

            var headers = new HttpHeaderCollection(new Dictionary <string, string>
            {
                { ":method", method },
                { ":path", path },
                { ":version", proto },
                {
                    ":scheme",
                    connection.GetType().FullName == "Ultz.SimpleServer.Common.SslListener.SecureConnection"
                        ? "https"
                        : "http"
                }
            }.Select(x => new HeaderField {
                Name = x.Key, Value = x.Value
            }));

            for (var i = 1; i < lines.Length; i++)
            {
                var line     = lines[i];
                var colonIdx = line.IndexOf(':');
                if (colonIdx == -1)
                {
                    throw new BadRequestException("Bad Request (HTTP/1 parser failure)");
                }
                var name  = line.Substring(0, colonIdx).Trim().ToLowerInvariant();
                var value = line.Substring(colonIdx + 1).Trim();
                if (name == "host")
                {
                    name = ":authority";
                }
                headers[name] = value;
            }

            return(new HttpParserOptional
            {
                ExpectPayload = methodResolver.GetMethod(Encoding.UTF8.GetBytes(headers[":method"])).ExpectPayload ||
                                headers.ContainsKey("content-length") && headers["content-length"] != "0",
                Headers = headers,
                MethodResolver = methodResolver,
                Payload = null
            });
        }