public async Task ReadExitsGivenIncompleteChunkedExtension()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderTransferEncoding = "chunked"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("5;\r\0");

                var buffer   = new byte[1024];
                var readTask = stream.ReadAsync(buffer, 0, buffer.Length);

                Assert.False(readTask.IsCompleted);

                input.Add("\r\r\r\nHello\r\n0\r\n\r\n");

                Assert.Equal(5, await readTask.DefaultTimeout());
                Assert.Equal(0, await stream.ReadAsync(buffer, 0, buffer.Length));

                await body.StopAsync();
            }
        }
        public async Task CanReadAsyncFromContentLength(HttpVersion httpVersion)
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(httpVersion, new HttpRequestHeaders {
                    HeaderContentLength = "5"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("Hello");

                var buffer = new byte[1024];

                var count = await stream.ReadAsync(buffer, 0, buffer.Length);

                Assert.Equal(5, count);
                AssertASCII("Hello", new ArraySegment <byte>(buffer, 0, count));

                count = await stream.ReadAsync(buffer, 0, buffer.Length);

                Assert.Equal(0, count);

                await body.StopAsync();
            }
        }
Beispiel #3
0
        public async Task CanReadAsyncFromChunkedEncoding()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderTransferEncoding = "chunked"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("5\r\nHello\r\n");

                var buffer = new byte[1024];

                var count = await stream.ReadAsync(buffer, 0, buffer.Length);

                Assert.Equal(5, count);
                AssertASCII("Hello", new ArraySegment <byte>(buffer, 0, count));

                input.Add("0\r\n\r\n");

                count = await stream.ReadAsync(buffer, 0, buffer.Length);

                Assert.Equal(0, count);

                input.Http1Connection.RequestBodyPipe.Reader.Complete();
                await body.StopAsync();
            }
        }
Beispiel #4
0
        internal async Task <MutableHttpServerRequest> ParseRequestStream(IInputStream requestStream)
        {
            var httpStream = new HttpRequestStream(requestStream);
            var request    = new MutableHttpServerRequest();

            try
            {
                var stream = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);

                byte[] streamData = stream.Data;

                var requestPipeline = GetPipeline();
                using (var pipeLineEnumerator = requestPipeline.GetEnumerator())
                {
                    pipeLineEnumerator.MoveNext();
                    bool requestComplete = false;

                    while (!requestComplete)
                    {
                        pipeLineEnumerator.Current.HandleRequestPart(streamData, request);
                        streamData = pipeLineEnumerator.Current.UnparsedData;

                        if (pipeLineEnumerator.Current.IsFinished)
                        {
                            if (!pipeLineEnumerator.Current.IsSucceeded ||
                                !pipeLineEnumerator.MoveNext())
                            {
                                break;
                            }
                        }
                        else
                        {
                            var newStreamdata = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);

                            if (!newStreamdata.ReadSuccessful)
                            {
                                break;
                            }

                            streamData = streamData.ConcatArray(newStreamdata.Data);
                        }
                    }
                }

                request.IsComplete = requestPipeline.All(p => p.IsSucceeded);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return(request);
        }
Beispiel #5
0
        internal async Task<HttpRequest> ParseRequestStream(IInputStream requestStream)
        {
            var httpStream = new HttpRequestStream(requestStream);
            var request = new HttpRequest();

            try
            {
                var stream = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);
                byte[] streamData = stream.Data;

                var requestPipeline = GetPipeline();
                using (var pipeLineEnumerator = requestPipeline.GetEnumerator())
                {
                    pipeLineEnumerator.MoveNext();
                    bool requestComplete = false;

                    while (!requestComplete)
                    {
                        pipeLineEnumerator.Current.HandleRequestPart(streamData, request);
                        streamData = pipeLineEnumerator.Current.UnparsedData;

                        if (pipeLineEnumerator.Current.IsFinished)
                        {
                            if (!pipeLineEnumerator.Current.IsSucceeded ||
                                !pipeLineEnumerator.MoveNext())
                            {
                                break;
                            }
                        }
                        else
                        {
                            var newStreamdata = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);

                            if (!newStreamdata.ReadSuccessful)
                            {
                                break;
                            }

                            streamData = streamData.ConcatArray(newStreamdata.Data);
                        }
                    }
                }

                request.IsComplete = requestPipeline.All(p => p.IsSucceeded);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return request;
        }
Beispiel #6
0
        public async Task SynchronousReadsThrowIfDisallowedByIHttpBodyControlFeature()
        {
            var allowSynchronousIO = false;
            var mockBodyControl    = new Mock <IHttpBodyControlFeature>();

            mockBodyControl.Setup(m => m.AllowSynchronousIO).Returns(() => allowSynchronousIO);
            var mockMessageBody = new Mock <MessageBody>((HttpProtocol)null);

            mockMessageBody.Setup(m => m.ReadAsync(It.IsAny <ArraySegment <byte> >(), CancellationToken.None)).ReturnsAsync(0);

            var stream = new HttpRequestStream(mockBodyControl.Object);

            stream.StartAcceptingReads(mockMessageBody.Object);

            Assert.Equal(0, await stream.ReadAsync(new byte[1], 0, 1));

            var ioEx = Assert.Throws <InvalidOperationException>(() => stream.Read(new byte[1], 0, 1));

            Assert.Equal("Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.", ioEx.Message);

            var ioEx2 = Assert.Throws <InvalidOperationException>(() => stream.CopyTo(Stream.Null));

            Assert.Equal("Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.", ioEx2.Message);

            allowSynchronousIO = true;
            Assert.Equal(0, stream.Read(new byte[1], 0, 1));
        }
        public async Task LogsWhenStopsReadingRequestBody()
        {
            using (var input = new TestInput())
            {
                var logEvent   = new ManualResetEventSlim();
                var mockLogger = new Mock <IKestrelTrace>();
                mockLogger
                .Setup(logger => logger.RequestBodyDone("ConnectionId", "RequestId"))
                .Callback(() => logEvent.Set());
                input.Http1Connection.ServiceContext.Log  = mockLogger.Object;
                input.Http1Connection.ConnectionIdFeature = "ConnectionId";
                input.Http1Connection.TraceIdentifier     = "RequestId";

                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "2"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                // Add some input and consume it to ensure PumpAsync is running
                input.Add("a");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                input.Fin();

                Assert.True(logEvent.Wait(TestConstants.DefaultTimeout));

                await body.StopAsync();
            }
        }
        public async Task UpgradeConnectionAcceptsContentLengthZero()
        {
            // https://tools.ietf.org/html/rfc7230#section-3.3.2
            // "A user agent SHOULD NOT send a Content-Length header field when the request message does not contain
            // a payload body and the method semantics do not anticipate such a body."
            //  ==> it can actually send that header
            var headerConnection = "Upgrade, Keep-Alive";

            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderConnection = headerConnection, ContentLength = 0
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("Hello");

                var buffer = new byte[1024];
                Assert.Equal(5, await stream.ReadAsync(buffer, 0, buffer.Length));
                AssertASCII("Hello", new ArraySegment <byte>(buffer, 0, 5));

                input.Fin();

                await body.StopAsync();
            }
        }
Beispiel #9
0
        public async Task LogsWhenStartsReadingRequestBody()
        {
            using (var input = new TestInput())
            {
                var mockLogger = new Mock <IKestrelTrace>();
                input.Http1Connection.ServiceContext.Log  = mockLogger.Object;
                input.Http1Connection.ConnectionIdFeature = "ConnectionId";
                input.Http1Connection.TraceIdentifier     = "RequestId";

                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "2"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                // Add some input and consume it to ensure PumpAsync is running
                input.Add("a");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                mockLogger.Verify(logger => logger.RequestBodyStart("ConnectionId", "RequestId"));

                input.Fin();

                input.Http1Connection.RequestBodyPipe.Reader.Complete();
                await body.StopAsync();
            }
        }
Beispiel #10
0
        public void StopAcceptingReadsCausesReadToThrowObjectDisposedException()
        {
            var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());

            stream.StartAcceptingReads(null);
            stream.StopAcceptingReads();
            Assert.Throws <ObjectDisposedException>(() => { stream.ReadAsync(new byte[1], 0, 1); });
        }
        public async Task AbortCausesReadToCancel()
        {
            var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());

            stream.StartAcceptingReads(null);
            stream.Abort();
            await Assert.ThrowsAsync <TaskCanceledException>(() => stream.ReadAsync(new byte[1], 0, 1));
        }
Beispiel #12
0
        public void AbortCausesReadToCancel()
        {
            var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());

            stream.StartAcceptingReads(null);
            stream.Abort();
            var task = stream.ReadAsync(new byte[1], 0, 1);

            Assert.True(task.IsCanceled);
        }
        public async Task AbortWithErrorCausesReadToCancel()
        {
            var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());

            stream.StartAcceptingReads(null);
            var error = new Exception();

            stream.Abort(error);
            var exception = await Assert.ThrowsAsync <Exception>(() => stream.ReadAsync(new byte[1], 0, 1));

            Assert.Same(error, exception);
        }
Beispiel #14
0
        public void AbortWithErrorCausesReadToCancel()
        {
            var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());

            stream.StartAcceptingReads(null);
            var error = new Exception();

            stream.Abort(error);
            var task = stream.ReadAsync(new byte[1], 0, 1);

            Assert.True(task.IsFaulted);
            Assert.Same(error, task.Exception.InnerException);
        }
        public async Task PumpAsyncDoesNotReturnAfterCancelingInput()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "2"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                // Add some input and consume it to ensure PumpAsync is running
                input.Add("a");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                input.Transport.Input.CancelPendingRead();

                // Add more input and verify is read
                input.Add("b");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                await body.StopAsync();
            }
        }
        public async Task StopAsyncPreventsFurtherDataConsumption()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "2"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                // Add some input and consume it to ensure PumpAsync is running
                input.Add("a");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                await body.StopAsync();

                // Add some more data. Checking for cancelation and exiting the loop
                // should take priority over reading this data.
                input.Add("b");

                // There shouldn't be any additional data available
                Assert.Equal(0, await stream.ReadAsync(new byte[1], 0, 1));
            }
        }
        public async Task ReadAsyncFromNoContentLengthReturnsZero(HttpVersion httpVersion)
        {
            using (var input = new TestInput())
            {
                var body   = Http1MessageBody.For(httpVersion, new HttpRequestHeaders(), input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("Hello");

                var buffer = new byte[1024];
                Assert.Equal(0, await stream.ReadAsync(buffer, 0, buffer.Length));

                await body.StopAsync();
            }
        }
        public async Task ConnectionUpgradeKeepAlive(string headerConnection)
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderConnection = headerConnection
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("Hello");

                var buffer = new byte[1024];
                Assert.Equal(5, await stream.ReadAsync(buffer, 0, buffer.Length));
                AssertASCII("Hello", new ArraySegment <byte>(buffer, 0, 5));

                input.Fin();

                await body.StopAsync();
            }
        }
        public async Task ReadThrowsGivenChunkPrefixGreaterThanMaxInt()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderTransferEncoding = "chunked"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("80000000\r\n");

                var buffer = new byte[1024];
                var ex     = await Assert.ThrowsAsync <IOException>(async() =>
                                                                    await stream.ReadAsync(buffer, 0, buffer.Length));

                Assert.IsType <OverflowException>(ex.InnerException);
                Assert.Equal(CoreStrings.BadRequest_BadChunkSizeData, ex.Message);

                await body.StopAsync();
            }
        }