Exemplo n.º 1
0
        public void ResponseHeaderParserAcceptsCustomStatusCodes(HttpStatusCode status)
        {
            byte[] data = CreateBuffer(
                "HTTP/1.1",
                ((int)status).ToString(),
                "Reason",
                ParserData.ValidHeaders
                );

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse     result = new HttpUnsortedResponse();
                HttpResponseHeaderParser parser = new HttpResponseHeaderParser(result);
                Assert.NotNull(parser);

                int         totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(ParserState.Done, state);
                Assert.Equal(data.Length, totalBytesConsumed);

                ValidateResult(
                    result,
                    new Version("1.1"),
                    status,
                    "Reason",
                    ParserData.ValidHeaders
                    );
            }
        }
Exemplo n.º 2
0
        public void ResponseHeaderParserAcceptsValidVersion(Version version)
        {
            byte[] data = CreateBuffer(
                String.Format("HTTP/{0}", version.ToString(2)),
                "200",
                "Reason",
                ParserData.ValidHeaders
                );

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse     result = new HttpUnsortedResponse();
                HttpResponseHeaderParser parser = new HttpResponseHeaderParser(result);
                Assert.NotNull(parser);

                int         totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(data.Length, totalBytesConsumed);

                ValidateResult(
                    result,
                    version,
                    HttpStatusCode.OK,
                    "Reason",
                    ParserData.ValidHeaders
                    );
            }
        }
Exemplo n.º 3
0
        public void HttpStatusLineParserConstructorTest()
        {
            HttpUnsortedResponse statusLine = new HttpUnsortedResponse();

            Assert.NotNull(statusLine);

            Assert.ThrowsArgumentGreaterThanOrEqualTo(
                () => new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize - 1),
                "maxStatusLineSize",
                ParserData.MinStatusLineSize.ToString(),
                ParserData.MinStatusLineSize - 1
                );

            HttpStatusLineParser parser = new HttpStatusLineParser(
                statusLine,
                ParserData.MinStatusLineSize
                );

            Assert.NotNull(parser);

            Assert.ThrowsArgumentNull(
                () =>
            {
                new HttpStatusLineParser(null, ParserData.MinStatusLineSize);
            },
                "httpResponse"
                );
        }
Exemplo n.º 4
0
        private static void ValidateResult(
            HttpUnsortedResponse statusLine,
            Version version,
            HttpStatusCode statusCode,
            string reasonPhrase,
            Dictionary <string, string> headers
            )
        {
            Assert.Equal(version, statusLine.Version);
            Assert.Equal(statusCode, statusLine.StatusCode);
            Assert.Equal(reasonPhrase, statusLine.ReasonPhrase);

            if (headers != null)
            {
                Assert.Equal(headers.Count, statusLine.HttpHeaders.Count());
                foreach (var header in headers)
                {
                    Assert.True(
                        statusLine.HttpHeaders.Contains(header.Key),
                        "Parsed header did not contain expected key " + header.Key
                        );
                    Assert.Equal(
                        header.Value,
                        statusLine.HttpHeaders.GetValues(header.Key).ElementAt(0)
                        );
                }
            }
        }
 public void StatusLineParserNullBuffer()
 {
     HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
     HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize);
     Assert.NotNull(parser);
     int bytesConsumed = 0;
     Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed); }, "buffer");
 }
        public void StatusLineParserNullBuffer()
        {
            HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
            HttpStatusLineParser parser     = new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize);

            Assert.NotNull(parser);
            int bytesConsumed = 0;

            Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed); }, "buffer");
        }
Exemplo n.º 7
0
 private static void ValidateResult(
     HttpUnsortedResponse statusLine,
     Version version,
     HttpStatusCode statusCode,
     string reasonPhrase
     )
 {
     Assert.Equal(version, statusLine.Version);
     Assert.Equal(statusCode, statusLine.StatusCode);
     Assert.Equal(reasonPhrase, statusLine.ReasonPhrase);
 }
        public void HttpStatusLineParserConstructorTest()
        {
            HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
            Assert.NotNull(statusLine);

            Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize - 1),
                "maxStatusLineSize", ParserData.MinStatusLineSize.ToString(), ParserData.MinStatusLineSize - 1);

            HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize);
            Assert.NotNull(parser);

            Assert.ThrowsArgumentNull(() => { new HttpStatusLineParser(null, ParserData.MinStatusLineSize); }, "httpResponse");
        }
        public void StatusLineParserRejectsLws()
        {
            byte[] data = CreateBuffer("HTTP/1.1", "200", "Reason", true);
            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                HttpStatusLineParser parser     = new HttpStatusLineParser(statusLine, data.Length);
                Assert.NotNull(parser);

                int         totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(ParserState.Invalid, state);
            }
        }
        public void StatusLineParserMinimumBuffer()
        {
            byte[] data = CreateBuffer("HTTP/1.1", "200", "");
            HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
            HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize);
            Assert.NotNull(parser);

            int bytesConsumed = 0;
            ParserState state = parser.ParseBuffer(data, data.Length, ref bytesConsumed);
            Assert.Equal(ParserState.Done, state);
            Assert.Equal(data.Length, bytesConsumed);

            ValidateResult(statusLine, new Version("1.1"), HttpStatusCode.OK, "");
        }
        public void StatusLineParserRejectsLws()
        {
            byte[] data = CreateBuffer("HTTP/1.1", "200", "Reason", true);
            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, data.Length);
                Assert.NotNull(parser);

                int totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(ParserState.Invalid, state);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpResponseHeaderParser"/> class.
        /// </summary>
        /// <param name="httpResponse">The parsed HTTP response without any header sorting.</param>
        /// <param name="maxResponseLineSize">The max length of the HTTP status line.</param>
        /// <param name="maxHeaderSize">The max length of the HTTP header.</param>
        public HttpResponseHeaderParser(HttpUnsortedResponse httpResponse, int maxResponseLineSize, int maxHeaderSize)
        {
            if (httpResponse == null)
            {
                throw new ArgumentNullException("httpResponse");
            }

            _httpResponse = httpResponse;

            // Create status line parser
            _statusLineParser = new HttpStatusLineParser(_httpResponse, maxResponseLineSize);

            // Create header parser
            _headerParser = new InternetMessageFormatHeaderParser(_httpResponse.HttpHeaders, maxHeaderSize);
        }
Exemplo n.º 13
0
        public void ResponseHeaderParserRejectsInvalidVersion(string invalid)
        {
            byte[] data = CreateBuffer(invalid, "200", "Reason", ParserData.ValidHeaders);

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse     result = new HttpUnsortedResponse();
                HttpResponseHeaderParser parser = new HttpResponseHeaderParser(result);
                Assert.NotNull(parser);

                int         totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(ParserState.Invalid, state);
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpResponseHeaderParser"/> class.
        /// </summary>
        /// <param name="httpResponse">The parsed HTTP response without any header sorting.</param>
        /// <param name="maxResponseLineSize">The max length of the HTTP status line.</param>
        /// <param name="maxHeaderSize">The max length of the HTTP header.</param>
        public HttpResponseHeaderParser(HttpUnsortedResponse httpResponse, int maxResponseLineSize, int maxHeaderSize)
        {
            if (httpResponse == null)
            {
                throw new ArgumentNullException("httpResponse");
            }

            _httpResponse = httpResponse;

            // Create status line parser
            _statusLineParser = new HttpStatusLineParser(_httpResponse, maxResponseLineSize);

            // Create header parser
            _headerParser = new InternetMessageFormatHeaderParser(_httpResponse.HttpHeaders, maxHeaderSize);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpStatusLineParser"/> class.
        /// </summary>
        /// <param name="httpResponse"><see cref="HttpUnsortedResponse"/> instance where the response line properties will be set as they are parsed.</param>
        /// <param name="maxStatusLineSize">Maximum length of HTTP header.</param>
        public HttpStatusLineParser(HttpUnsortedResponse httpResponse, int maxStatusLineSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxStatusLineSize < MinStatusLineSize)
            {
                throw new ArgumentOutOfRangeException("maxStatusLineSize", maxStatusLineSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MinStatusLineSize));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException("httpResponse");
            }

            _httpResponse = httpResponse;
            _maximumHeaderLength = maxStatusLineSize;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpStatusLineParser"/> class.
        /// </summary>
        /// <param name="httpResponse"><see cref="HttpUnsortedResponse"/> instance where the response line properties will be set as they are parsed.</param>
        /// <param name="maxStatusLineSize">Maximum length of HTTP header.</param>
        public HttpStatusLineParser(HttpUnsortedResponse httpResponse, int maxStatusLineSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxStatusLineSize < MinStatusLineSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("maxStatusLineSize", maxStatusLineSize, MinStatusLineSize);
            }

            if (httpResponse == null)
            {
                throw Error.ArgumentNull("httpResponse");
            }

            this._httpResponse = httpResponse;
            this._maximumHeaderLength = maxStatusLineSize;
        }
        public void StatusLineParserMinimumBuffer()
        {
            byte[] data = CreateBuffer("HTTP/1.1", "200", "");
            HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
            HttpStatusLineParser parser     = new HttpStatusLineParser(statusLine, ParserData.MinStatusLineSize);

            Assert.NotNull(parser);

            int         bytesConsumed = 0;
            ParserState state         = parser.ParseBuffer(data, data.Length, ref bytesConsumed);

            Assert.Equal(ParserState.Done, state);
            Assert.Equal(data.Length, bytesConsumed);

            ValidateResult(statusLine, new Version("1.1"), HttpStatusCode.OK, "");
        }
Exemplo n.º 18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpStatusLineParser"/> class.
        /// </summary>
        /// <param name="httpResponse"><see cref="HttpUnsortedResponse"/> instance where the response line properties will be set as they are parsed.</param>
        /// <param name="maxStatusLineSize">Maximum length of HTTP header.</param>
        public HttpStatusLineParser(HttpUnsortedResponse httpResponse, int maxStatusLineSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxStatusLineSize < MinStatusLineSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("maxStatusLineSize", maxStatusLineSize, MinStatusLineSize);
            }

            if (httpResponse == null)
            {
                throw Error.ArgumentNull("httpResponse");
            }

            this._httpResponse        = httpResponse;
            this._maximumHeaderLength = maxStatusLineSize;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpStatusLineParser"/> class.
        /// </summary>
        /// <param name="httpResponse"><see cref="HttpUnsortedResponse"/> instance where the response line properties will be set as they are parsed.</param>
        /// <param name="maxStatusLineSize">Maximum length of HTTP header.</param>
        public HttpStatusLineParser(HttpUnsortedResponse httpResponse, int maxStatusLineSize)
        {
            // The minimum length which would be an empty header terminated by CRLF
            if (maxStatusLineSize < MinStatusLineSize)
            {
                throw new ArgumentOutOfRangeException("maxStatusLineSize", maxStatusLineSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MinStatusLineSize));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException("httpResponse");
            }

            _httpResponse        = httpResponse;
            _maximumHeaderLength = maxStatusLineSize;
        }
        public void StatusLineParserAcceptsValidReasonPhrase(string validReasonPhrase)
        {
            byte[] data = CreateBuffer("HTTP/1.1", "200", validReasonPhrase);

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                HttpStatusLineParser parser     = new HttpStatusLineParser(statusLine, 256);
                Assert.NotNull(parser);

                int         totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);

                ValidateResult(statusLine, new Version("1.1"), HttpStatusCode.OK, validReasonPhrase);
            }
        }
        public void StatusLineParserAcceptsStandardStatusCodes(HttpStatusCode status)
        {
            byte[] data = CreateBuffer("HTTP/1.1", ((int)status).ToString(), "Reason");

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, data.Length);
                Assert.NotNull(parser);

                int totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(ParserState.Done, state);
                Assert.Equal(data.Length, totalBytesConsumed);

                ValidateResult(statusLine, new Version("1.1"), status, "Reason");
            }
        }
        public void StatusLineParserRejectsInvalidStatusCodes()
        {
            foreach (string invalidStatus in ParserData.InvalidStatusCodes)
            {
                byte[] data = CreateBuffer("HTTP/1.1", invalidStatus, "Reason");

                for (var cnt = 1; cnt <= data.Length; cnt++)
                {
                    HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                    HttpStatusLineParser parser     = new HttpStatusLineParser(statusLine, 256);
                    Assert.NotNull(parser);

                    int         totalBytesConsumed = 0;
                    ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                    Assert.Equal(ParserState.Invalid, state);
                }
            }
        }
        private static void ValidateResult(
            HttpUnsortedResponse statusLine,
            Version version,
            HttpStatusCode statusCode,
            string reasonPhrase,
            Dictionary<string, string> headers)
        {
            Assert.Equal(version, statusLine.Version);
            Assert.Equal(statusCode, statusLine.StatusCode);
            Assert.Equal(reasonPhrase, statusLine.ReasonPhrase);

            if (headers != null)
            {
                Assert.Equal(headers.Count, statusLine.HttpHeaders.Count());
                foreach (var header in headers)
                {
                    Assert.True(statusLine.HttpHeaders.Contains(header.Key), "Parsed header did not contain expected key " + header.Key);
                    Assert.Equal(header.Value, statusLine.HttpHeaders.GetValues(header.Key).ElementAt(0));
                }
            }
        }
        public void StatusLineParserAcceptsCustomStatusCodes()
        {
            foreach (HttpStatusCode status in HttpUnitTestDataSets.CustomHttpStatusCodes)
            {
                byte[] data = CreateBuffer("HTTP/1.1", ((int)status).ToString(), "Reason");

                for (var cnt = 1; cnt <= data.Length; cnt++)
                {
                    HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                    HttpStatusLineParser parser     = new HttpStatusLineParser(statusLine, data.Length);
                    Assert.NotNull(parser);

                    int         totalBytesConsumed = 0;
                    ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                    Assert.Equal(ParserState.Done, state);
                    Assert.Equal(data.Length, totalBytesConsumed);

                    ValidateResult(statusLine, new Version("1.1"), status, "Reason");
                }
            }
        }
Exemplo n.º 25
0
        private static ParserState ParseStatusLine(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref HttpStatusLineState statusLineState,
            int maximumHeaderLength,
            ref int totalBytesConsumed,
            StringBuilder currentToken,
            HttpUnsortedResponse httpResponse)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseRequestLine()|(bytesReady - bytesConsumed) < 0");
            Contract.Assert(maximumHeaderLength <= 0 || totalBytesConsumed <= maximumHeaderLength, "ParseRequestLine()|Headers already read exceeds limit.");

            // Remember where we started.
            int initialBytesParsed = bytesConsumed;
            int segmentStart;

            // Set up parsing status with what will happen if we exceed the buffer.
            ParserState parseStatus  = ParserState.DataTooBig;
            int         effectiveMax = maximumHeaderLength <= 0 ? Int32.MaxValue : (maximumHeaderLength - totalBytesConsumed + bytesConsumed);

            if (bytesReady < effectiveMax)
            {
                parseStatus  = ParserState.NeedMoreData;
                effectiveMax = bytesReady;
            }

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (statusLineState)
            {
            case HttpStatusLineState.BeforeVersionNumbers:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != '/')
                {
                    if (buffer[bytesConsumed] < 0x21 || buffer[bytesConsumed] > 0x7a)
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string token = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(token);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string token = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentToken.Append(token);
                }

                // Validate value
                string version = currentToken.ToString();
                if (String.CompareOrdinal(FormattingUtilities.HttpVersionToken, version) != 0)
                {
                    throw new FormatException(Error.Format(Resources.HttpInvalidVersion, version, FormattingUtilities.HttpVersionToken));
                }

                currentToken.Clear();

                // Move past the '/'
                statusLineState = HttpStatusLineState.MajorVersionNumber;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HttpStatusLineState.MajorVersionNumber;

            case HttpStatusLineState.MajorVersionNumber:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != '.')
                {
                    if (buffer[bytesConsumed] < '0' || buffer[bytesConsumed] > '9')
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string major = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(major);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string major = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentToken.Append(major);
                }

                // Move past the "."
                currentToken.Append('.');
                statusLineState = HttpStatusLineState.MinorVersionNumber;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HttpStatusLineState.MinorVersionNumber;

            case HttpStatusLineState.MinorVersionNumber:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != ' ')
                {
                    if (buffer[bytesConsumed] < '0' || buffer[bytesConsumed] > '9')
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string minor = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(minor);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string minor = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentToken.Append(minor);
                }

                // Copy out value
                httpResponse.Version = Version.Parse(currentToken.ToString());
                currentToken.Clear();

                // Move past the SP
                statusLineState = HttpStatusLineState.StatusCode;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HttpStatusLineState.StatusCode;

            case HttpStatusLineState.StatusCode:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != ' ')
                {
                    if (buffer[bytesConsumed] < '0' || buffer[bytesConsumed] > '9')
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string method = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(method);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string method = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentToken.Append(method);
                }

                // Copy value out
                int statusCode = Int32.Parse(currentToken.ToString(), CultureInfo.InvariantCulture);
                if (statusCode < 100 || statusCode > 1000)
                {
                    throw new FormatException(Error.Format(Resources.HttpInvalidStatusCode, statusCode, 100, 1000));
                }

                httpResponse.StatusCode = (HttpStatusCode)statusCode;
                currentToken.Clear();

                // Move past the SP
                statusLineState = HttpStatusLineState.ReasonPhrase;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HttpStatusLineState.ReasonPhrase;

            case HttpStatusLineState.ReasonPhrase:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != '\r')
                {
                    if (buffer[bytesConsumed] < 0x20 || buffer[bytesConsumed] > 0x7a)
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string addr = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(addr);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string addr = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentToken.Append(addr);
                }

                // Copy value out
                httpResponse.ReasonPhrase = currentToken.ToString();
                currentToken.Clear();

                // Move past the CR
                statusLineState = HttpStatusLineState.AfterCarriageReturn;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HttpStatusLineState.AfterCarriageReturn;

            case HttpStatusLineState.AfterCarriageReturn:
                if (buffer[bytesConsumed] != '\n')
                {
                    parseStatus = ParserState.Invalid;
                    goto quit;
                }

                parseStatus = ParserState.Done;
                bytesConsumed++;
                break;
            }

quit:
            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return(parseStatus);
        }
        public void ResponseHeaderParserRejectsInvalidVersion(string invalid)
        {
            byte[] data = CreateBuffer(invalid, "200", "Reason", ParserData.ValidHeaders);

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse result = new HttpUnsortedResponse();
                HttpResponseHeaderParser parser = new HttpResponseHeaderParser(result);
                Assert.NotNull(parser);

                int totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(ParserState.Invalid, state);
            }
        }
        public void StatusLineParserRejectsInvalidStatusCodes()
        {
            foreach (string invalidStatus in ParserData.InvalidStatusCodes)
            {
                byte[] data = CreateBuffer("HTTP/1.1", invalidStatus, "Reason");

                for (var cnt = 1; cnt <= data.Length; cnt++)
                {
                    HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                    HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, 256);
                    Assert.NotNull(parser);

                    int totalBytesConsumed = 0;
                    ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                    Assert.Equal(ParserState.Invalid, state);
                }
            }
        }
        public void ResponseHeaderParserAcceptsCustomStatusCodes()
        {
            foreach (HttpStatusCode status in HttpUnitTestDataSets.CustomHttpStatusCodes)
            {
                byte[] data = CreateBuffer("HTTP/1.1", ((int)status).ToString(), "Reason", ParserData.ValidHeaders);

                for (var cnt = 1; cnt <= data.Length; cnt++)
                {
                    HttpUnsortedResponse result = new HttpUnsortedResponse();
                    HttpResponseHeaderParser parser = new HttpResponseHeaderParser(result);
                    Assert.NotNull(parser);

                    int totalBytesConsumed = 0;
                    ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                    Assert.Equal(ParserState.Done, state);
                    Assert.Equal(data.Length, totalBytesConsumed);

                    ValidateResult(result, new Version("1.1"), status, "Reason", ParserData.ValidHeaders);
                }
            }
        }
 private static void ValidateResult(HttpUnsortedResponse statusLine, Version version, HttpStatusCode statusCode, string reasonPhrase)
 {
     Assert.Equal(version, statusLine.Version);
     Assert.Equal(statusCode, statusLine.StatusCode);
     Assert.Equal(reasonPhrase, statusLine.ReasonPhrase);
 }
        public void StatusLineParserAcceptsValidVersion(Version version)
        {
            byte[] data = CreateBuffer(String.Format("HTTP/{0}", version.ToString(2)), "200", "Reason");

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, 256);
                Assert.NotNull(parser);

                int totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
                Assert.Equal(data.Length, totalBytesConsumed);

                ValidateResult(statusLine, version, HttpStatusCode.OK, "Reason");
            }
        }
        public void StatusLineParserAcceptsValidReasonPhrase(string validReasonPhrase)
        {
            byte[] data = CreateBuffer("HTTP/1.1", "200", validReasonPhrase);

            for (var cnt = 1; cnt <= data.Length; cnt++)
            {
                HttpUnsortedResponse statusLine = new HttpUnsortedResponse();
                HttpStatusLineParser parser = new HttpStatusLineParser(statusLine, 256);
                Assert.NotNull(parser);

                int totalBytesConsumed = 0;
                ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);

                ValidateResult(statusLine, new Version("1.1"), HttpStatusCode.OK, validReasonPhrase);
            }
        }
        private static HttpResponseMessage CreateHttpResponseMessage(HttpUnsortedResponse httpResponse, Stream contentStream, int rewind)
        {
            Contract.Assert(httpResponse != null, "httpResponse must be non null");
            Contract.Assert(contentStream != null, "contentStream must be non null");

            HttpResponseMessage httpResponseMessage = new HttpResponseMessage();

            // Set version, status code and reason phrase
            httpResponseMessage.Version = httpResponse.Version;
            httpResponseMessage.StatusCode = httpResponse.StatusCode;
            httpResponseMessage.ReasonPhrase = httpResponse.ReasonPhrase;

            // Set the header fields and content if any
            httpResponseMessage.Content = CreateHeaderFields(httpResponse.HttpHeaders, httpResponseMessage.Headers, contentStream, rewind);

            return httpResponseMessage;
        }
        private static async Task<HttpResponseMessage> ReadAsHttpResponseMessageAsyncCore(this HttpContent content,
            int bufferSize, int maxHeaderSize, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            Stream stream = await content.ReadAsStreamAsync();

            HttpUnsortedResponse httpResponse = new HttpUnsortedResponse();
            HttpResponseHeaderParser parser = new HttpResponseHeaderParser(httpResponse, HttpResponseHeaderParser.DefaultMaxStatusLineSize, maxHeaderSize);
            ParserState parseStatus;

            byte[] buffer = new byte[bufferSize];
            int bytesRead = 0;
            int headerConsumed = 0;

            while (true)
            {
                try
                {
                    bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                }
                catch (Exception e)
                {
                    throw new IOException(Resources.HttpMessageErrorReading, e);
                }

                try
                {
                    parseStatus = parser.ParseBuffer(buffer, bytesRead, ref headerConsumed);
                }
                catch (Exception)
                {
                    parseStatus = ParserState.Invalid;
                }

                if (parseStatus == ParserState.Done)
                {
                    // Create and return parsed HttpResponseMessage
                    return CreateHttpResponseMessage(httpResponse, stream, bytesRead - headerConsumed);
                }
                else if (parseStatus != ParserState.NeedMoreData)
                {
                    throw Error.InvalidOperation(Resources.HttpMessageParserError, headerConsumed, buffer);
                }
                else if (bytesRead == 0)
                {
                    throw new IOException(Resources.ReadAsHttpMessageUnexpectedTermination);
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="HttpResponseHeaderParser"/> class.
 /// </summary>
 /// <param name="httpResponse">The parsed HTTP response without any header sorting.</param>
 public HttpResponseHeaderParser(HttpUnsortedResponse httpResponse)
     : this(httpResponse, DefaultMaxStatusLineSize, DefaultMaxHeaderSize)
 {
 }
        private static ParserState ParseStatusLine(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref HttpStatusLineState statusLineState,
            int maximumHeaderLength,
            ref int totalBytesConsumed,
            StringBuilder currentToken,
            HttpUnsortedResponse httpResponse)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseRequestLine()|(bytesReady - bytesConsumed) < 0");
            Contract.Assert(maximumHeaderLength <= 0 || totalBytesConsumed <= maximumHeaderLength, "ParseRequestLine()|Headers already read exceeds limit.");

            // Remember where we started.
            int initialBytesParsed = bytesConsumed;
            int segmentStart;

            // Set up parsing status with what will happen if we exceed the buffer.
            ParserState parseStatus = ParserState.DataTooBig;
            int effectiveMax = maximumHeaderLength <= 0 ? Int32.MaxValue : (maximumHeaderLength - totalBytesConsumed + bytesConsumed);
            if (bytesReady < effectiveMax)
            {
                parseStatus = ParserState.NeedMoreData;
                effectiveMax = bytesReady;
            }

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (statusLineState)
            {
                case HttpStatusLineState.BeforeVersionNumbers:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != '/')
                    {
                        if (buffer[bytesConsumed] < 0x21 || buffer[bytesConsumed] > 0x7a)
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string token = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentToken.Append(token);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string token = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(token);
                    }

                    // Validate value
                    string version = currentToken.ToString();
                    if (String.CompareOrdinal(FormattingUtilities.HttpVersionToken, version) != 0)
                    {
                        throw new FormatException(RS.Format(Properties.Resources.HttpInvalidVersion, version, FormattingUtilities.HttpVersionToken));
                    }

                    currentToken.Clear();

                    // Move past the '/'
                    statusLineState = HttpStatusLineState.MajorVersionNumber;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HttpStatusLineState.MajorVersionNumber;

                case HttpStatusLineState.MajorVersionNumber:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != '.')
                    {
                        if (buffer[bytesConsumed] < '0' || buffer[bytesConsumed] > '9')
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string major = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentToken.Append(major);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string major = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(major);
                    }

                    // Move past the "."
                    currentToken.Append('.');
                    statusLineState = HttpStatusLineState.MinorVersionNumber;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HttpStatusLineState.MinorVersionNumber;

                case HttpStatusLineState.MinorVersionNumber:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != ' ')
                    {
                        if (buffer[bytesConsumed] < '0' || buffer[bytesConsumed] > '9')
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string minor = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentToken.Append(minor);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string minor = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(minor);
                    }

                    // Copy out value
                    httpResponse.Version = Version.Parse(currentToken.ToString());
                    currentToken.Clear();

                    // Move past the SP
                    statusLineState = HttpStatusLineState.StatusCode;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HttpStatusLineState.StatusCode;

                case HttpStatusLineState.StatusCode:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != ' ')
                    {
                        if (buffer[bytesConsumed] < '0' || buffer[bytesConsumed] > '9')
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string method = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentToken.Append(method);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string method = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(method);
                    }

                    // Copy value out
                    int statusCode = Int32.Parse(currentToken.ToString(), CultureInfo.InvariantCulture);
                    if (statusCode < 100 || statusCode > 1000)
                    {
                        throw new FormatException(RS.Format(Properties.Resources.HttpInvalidStatusCode, statusCode, 100, 1000));
                    }

                    httpResponse.StatusCode = (HttpStatusCode)statusCode;
                    currentToken.Clear();

                    // Move past the SP
                    statusLineState = HttpStatusLineState.ReasonPhrase;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HttpStatusLineState.ReasonPhrase;

                case HttpStatusLineState.ReasonPhrase:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != '\r')
                    {
                        if (buffer[bytesConsumed] < 0x20 || buffer[bytesConsumed] > 0x7a)
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string addr = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentToken.Append(addr);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string addr = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentToken.Append(addr);
                    }

                    // Copy value out
                    httpResponse.ReasonPhrase = currentToken.ToString();
                    currentToken.Clear();

                    // Move past the CR
                    statusLineState = HttpStatusLineState.AfterCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HttpStatusLineState.AfterCarriageReturn;

                case HttpStatusLineState.AfterCarriageReturn:
                    if (buffer[bytesConsumed] != '\n')
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    parseStatus = ParserState.Done;
                    bytesConsumed++;
                    break;
            }

        quit:
            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return parseStatus;
        }
Exemplo n.º 36
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HttpResponseHeaderParser"/> class.
 /// </summary>
 /// <param name="httpResponse">The parsed HTTP response without any header sorting.</param>
 public HttpResponseHeaderParser(HttpUnsortedResponse httpResponse)
     : this(httpResponse, DefaultMaxStatusLineSize, DefaultMaxHeaderSize)
 {
 }