|
@@ -20,10 +20,11 @@ namespace Microsoft.AspNetCore.TestHost
|
|
|
|
|
|
|
|
private readonly TaskCompletionSource<HttpContext> _responseTcs = new TaskCompletionSource<HttpContext>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
private readonly TaskCompletionSource<HttpContext> _responseTcs = new TaskCompletionSource<HttpContext>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
private readonly ResponseStream _responseStream;
|
|
private readonly ResponseStream _responseStream;
|
|
|
- private readonly ResponseFeature _responseFeature = new ResponseFeature();
|
|
|
|
|
|
|
+ private readonly ResponseFeature _responseFeature;
|
|
|
private readonly RequestLifetimeFeature _requestLifetimeFeature = new RequestLifetimeFeature();
|
|
private readonly RequestLifetimeFeature _requestLifetimeFeature = new RequestLifetimeFeature();
|
|
|
private readonly ResponseTrailersFeature _responseTrailersFeature = new ResponseTrailersFeature();
|
|
private readonly ResponseTrailersFeature _responseTrailersFeature = new ResponseTrailersFeature();
|
|
|
private bool _pipelineFinished;
|
|
private bool _pipelineFinished;
|
|
|
|
|
+ private bool _returningResponse;
|
|
|
private Context _testContext;
|
|
private Context _testContext;
|
|
|
private Action<HttpContext> _responseReadCompleteCallback;
|
|
private Action<HttpContext> _responseReadCompleteCallback;
|
|
|
|
|
|
|
@@ -33,6 +34,7 @@ namespace Microsoft.AspNetCore.TestHost
|
|
|
AllowSynchronousIO = allowSynchronousIO;
|
|
AllowSynchronousIO = allowSynchronousIO;
|
|
|
_preserveExecutionContext = preserveExecutionContext;
|
|
_preserveExecutionContext = preserveExecutionContext;
|
|
|
_httpContext = new DefaultHttpContext();
|
|
_httpContext = new DefaultHttpContext();
|
|
|
|
|
+ _responseFeature = new ResponseFeature(Abort);
|
|
|
|
|
|
|
|
var request = _httpContext.Request;
|
|
var request = _httpContext.Request;
|
|
|
request.Protocol = "HTTP/1.1";
|
|
request.Protocol = "HTTP/1.1";
|
|
@@ -40,6 +42,7 @@ namespace Microsoft.AspNetCore.TestHost
|
|
|
|
|
|
|
|
_httpContext.Features.Set<IHttpBodyControlFeature>(this);
|
|
_httpContext.Features.Set<IHttpBodyControlFeature>(this);
|
|
|
_httpContext.Features.Set<IHttpResponseFeature>(_responseFeature);
|
|
_httpContext.Features.Set<IHttpResponseFeature>(_responseFeature);
|
|
|
|
|
+ _httpContext.Features.Set<IHttpResponseStartFeature>(_responseFeature);
|
|
|
_httpContext.Features.Set<IHttpRequestLifetimeFeature>(_requestLifetimeFeature);
|
|
_httpContext.Features.Set<IHttpRequestLifetimeFeature>(_requestLifetimeFeature);
|
|
|
_httpContext.Features.Set<IHttpResponseTrailersFeature>(_responseTrailersFeature);
|
|
_httpContext.Features.Set<IHttpResponseTrailersFeature>(_responseTrailersFeature);
|
|
|
|
|
|
|
@@ -132,12 +135,13 @@ namespace Microsoft.AspNetCore.TestHost
|
|
|
|
|
|
|
|
internal async Task ReturnResponseMessageAsync()
|
|
internal async Task ReturnResponseMessageAsync()
|
|
|
{
|
|
{
|
|
|
- // Check if the response has already started because the TrySetResult below could happen a bit late
|
|
|
|
|
|
|
+ // Check if the response is already returning because the TrySetResult below could happen a bit late
|
|
|
// (as it happens on a different thread) by which point the CompleteResponseAsync could run and calls this
|
|
// (as it happens on a different thread) by which point the CompleteResponseAsync could run and calls this
|
|
|
// method again.
|
|
// method again.
|
|
|
- if (!_responseFeature.HasStarted)
|
|
|
|
|
|
|
+ if (!_returningResponse)
|
|
|
{
|
|
{
|
|
|
- // Sets HasStarted
|
|
|
|
|
|
|
+ _returningResponse = true;
|
|
|
|
|
+
|
|
|
try
|
|
try
|
|
|
{
|
|
{
|
|
|
await _responseFeature.FireOnSendingHeadersAsync();
|
|
await _responseFeature.FireOnSendingHeadersAsync();
|