/// <summary>
        /// Start processing the request.
        /// </summary>
        /// <returns></returns>
        internal Task <HttpContext> SendAsync(CancellationToken cancellationToken)
        {
            var registration = cancellationToken.Register(ClientInitiatedAbort);

            // Everything inside this function happens in the SERVER's execution context (unless PreserveExecutionContext is true)
            async Task RunRequestAsync()
            {
                // HTTP/2 specific features must be added after the request has been configured.
                if (HttpProtocol.IsHttp2(_httpContext.Request.Protocol))
                {
                    _httpContext.Features.Set <IHttpResetFeature>(this);
                }

                // This will configure IHttpContextAccessor so it needs to happen INSIDE this function,
                // since we are now inside the Server's execution context. If it happens outside this cont
                // it will be lost when we abandon the execution context.
                _testContext = _application.CreateContext(_httpContext.Features);
                try
                {
                    await _application.ProcessRequestAsync(_testContext);

                    // Determine whether request body was complete when the delegate exited.
                    // This could throw an error if there was a pending server read. Needs to
                    // happen before completing the response so the response returns the error.
                    var requestBodyInProgress = RequestBodyReadInProgress();

                    // Matches Kestrel server: response is completed before request is drained
                    await CompleteResponseAsync();
                    await CompleteRequestAsync(requestBodyInProgress);

                    _application.DisposeContext(_testContext, exception: null);
                }
                catch (Exception ex)
                {
                    Abort(ex);
                    _application.DisposeContext(_testContext, ex);
                }
                finally
                {
                    registration.Dispose();
                }
            }

            // Async offload, don't let the test code block the caller.
            if (_preserveExecutionContext)
            {
                _ = Task.Factory.StartNew(RunRequestAsync);
            }
            else
            {
                ThreadPool.UnsafeQueueUserWorkItem(_ =>
                {
                    _ = RunRequestAsync();
                }, null);
            }

            return(_responseTcs.Task);
        }
        /// <summary>
        /// Start processing the request.
        /// </summary>
        /// <returns></returns>
        internal Task <HttpContext> SendAsync(CancellationToken cancellationToken)
        {
            var registration = cancellationToken.Register(ClientInitiatedAbort);

            // Everything inside this function happens in the SERVER's execution context (unless PreserveExecutionContext is true)
            async Task RunRequestAsync()
            {
                // HTTP/2 specific features must be added after the request has been configured.
                if (string.Equals("HTTP/2", _httpContext.Request.Protocol, StringComparison.OrdinalIgnoreCase))
                {
                    _httpContext.Features.Set <IHttpResetFeature>(this);
                }

                // This will configure IHttpContextAccessor so it needs to happen INSIDE this function,
                // since we are now inside the Server's execution context. If it happens outside this cont
                // it will be lost when we abandon the execution context.
                _testContext = _application.CreateContext(_httpContext.Features);
                try
                {
                    await _application.ProcessRequestAsync(_testContext);
                    await CompleteRequestAsync();
                    await CompleteResponseAsync();

                    _application.DisposeContext(_testContext, exception: null);
                }
                catch (Exception ex)
                {
                    Abort(ex);
                    _application.DisposeContext(_testContext, ex);
                }
                finally
                {
                    registration.Dispose();
                }
            }

            // Async offload, don't let the test code block the caller.
            if (_preserveExecutionContext)
            {
                _ = Task.Factory.StartNew(RunRequestAsync);
            }
            else
            {
                ThreadPool.UnsafeQueueUserWorkItem(_ =>
                {
                    _ = RunRequestAsync();
                }, null);
            }

            return(_responseTcs.Task);
        }
示例#3
0
        /// <summary>
        /// Start processing the request.
        /// </summary>
        /// <returns></returns>
        internal Task <HttpContext> SendAsync(CancellationToken cancellationToken)
        {
            var registration = cancellationToken.Register(AbortRequest);

            // Everything inside this function happens in the SERVER's execution context (unless PreserveExecutionContext is true)
            async Task RunRequestAsync()
            {
                // This will configure IHttpContextAccessor so it needs to happen INSIDE this function,
                // since we are now inside the Server's execution context. If it happens outside this cont
                // it will be lost when we abandon the execution context.
                _testContext = _application.CreateContext(_httpContext.Features);

                try
                {
                    await _application.ProcessRequestAsync(_testContext);
                    await CompleteResponseAsync();

                    _application.DisposeContext(_testContext, exception: null);
                }
                catch (Exception ex)
                {
                    Abort(ex);
                    _application.DisposeContext(_testContext, ex);
                }
                finally
                {
                    registration.Dispose();
                }
            }

            // Async offload, don't let the test code block the caller.
            if (_preserveExecutionContext)
            {
                _ = Task.Factory.StartNew(RunRequestAsync);
            }
            else
            {
                ThreadPool.UnsafeQueueUserWorkItem(_ =>
                {
                    _ = RunRequestAsync();
                }, null);
            }

            return(_responseTcs.Task);
        }
示例#4
0
        /// <summary>
        /// Start processing the request.
        /// </summary>
        /// <returns></returns>
        internal Task <HttpContext> SendAsync(CancellationToken cancellationToken)
        {
            var registration = cancellationToken.Register(ClientInitiatedAbort);

            // Everything inside this function happens in the SERVER's execution context (unless PreserveExecutionContext is true)
            async Task RunRequestAsync()
            {
                // HTTP/2 specific features must be added after the request has been configured.
                if (HttpProtocol.IsHttp2(_httpContext.Request.Protocol))
                {
                    _httpContext.Features.Set <IHttpResetFeature>(this);
                }

                // This will configure IHttpContextAccessor so it needs to happen INSIDE this function,
                // since we are now inside the Server's execution context. If it happens outside this cont
                // it will be lost when we abandon the execution context.
                _testContext = _application.CreateContext(_httpContext.Features);
                try
                {
                    await _application.ProcessRequestAsync(_testContext);

                    // Determine whether request body was complete when the delegate exited.
                    // This could throw an error if there was a pending server read. Needs to
                    // happen before completing the response so the response returns the error.
                    var requestBodyInProgress = RequestBodyReadInProgress();
                    if (requestBodyInProgress)
                    {
                        // If request is still in progress then abort it.
                        CancelRequestBody();
                    }

                    // Matches Kestrel server: response is completed before request is drained
                    await CompleteResponseAsync();

                    if (!requestBodyInProgress)
                    {
                        // Writer was already completed in send request callback.
                        await _requestPipe.Reader.CompleteAsync();

                        // Don't wait for request to drain. It could block indefinitely. In a real server
                        // we would wait for a timeout and then kill the socket.
                        // Potential future improvement: add logging that the request timed out
                    }

                    _application.DisposeContext(_testContext, exception: null);
                }
                catch (Exception ex)
                {
                    Abort(ex);
                    _application.DisposeContext(_testContext, ex);
                }
                finally
                {
                    registration.Dispose();
                }
            }

            // Async offload, don't let the test code block the caller.
            if (_preserveExecutionContext)
            {
                _ = Task.Factory.StartNew(RunRequestAsync, default, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);