Check HasStarted before calling Flush/Start in StartAsync (#8041)
This commit is contained in:
parent
3509323ad1
commit
5fd53d9d07
|
|
@ -151,6 +151,11 @@ namespace Microsoft.AspNetCore.Http.Internal
|
||||||
|
|
||||||
public override Task StartAsync(CancellationToken cancellationToken = default)
|
public override Task StartAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
if (HasStarted)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
if (HttpResponseStartFeature == null)
|
if (HttpResponseStartFeature == null)
|
||||||
{
|
{
|
||||||
return HttpResponseFeature.Body.FlushAsync(cancellationToken);
|
return HttpResponseFeature.Body.FlushAsync(cancellationToken);
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,10 @@ namespace Microsoft.AspNetCore.Http.Internal
|
||||||
mock.Setup(o => o.StartAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
|
mock.Setup(o => o.StartAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
|
||||||
features.Set(mock.Object);
|
features.Set(mock.Object);
|
||||||
|
|
||||||
|
var responseMock = new Mock<IHttpResponseFeature>();
|
||||||
|
responseMock.Setup(o => o.HasStarted).Returns(false);
|
||||||
|
features.Set(responseMock.Object);
|
||||||
|
|
||||||
var context = new DefaultHttpContext(features);
|
var context = new DefaultHttpContext(features);
|
||||||
await context.Response.StartAsync();
|
await context.Response.StartAsync();
|
||||||
|
|
||||||
|
|
@ -126,12 +130,35 @@ namespace Microsoft.AspNetCore.Http.Internal
|
||||||
mock.Setup(o => o.StartAsync(It.Is<CancellationToken>((localCt) => localCt.Equals(ct)))).Returns(Task.CompletedTask);
|
mock.Setup(o => o.StartAsync(It.Is<CancellationToken>((localCt) => localCt.Equals(ct)))).Returns(Task.CompletedTask);
|
||||||
features.Set(mock.Object);
|
features.Set(mock.Object);
|
||||||
|
|
||||||
|
var responseMock = new Mock<IHttpResponseFeature>();
|
||||||
|
responseMock.Setup(o => o.HasStarted).Returns(false);
|
||||||
|
features.Set(responseMock.Object);
|
||||||
|
|
||||||
var context = new DefaultHttpContext(features);
|
var context = new DefaultHttpContext(features);
|
||||||
await context.Response.StartAsync(ct);
|
await context.Response.StartAsync(ct);
|
||||||
|
|
||||||
mock.Verify(m => m.StartAsync(default), Times.Once());
|
mock.Verify(m => m.StartAsync(default), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ResponseStart_DoesNotCallStartIfHasStartedIsTrue()
|
||||||
|
{
|
||||||
|
var features = new FeatureCollection();
|
||||||
|
|
||||||
|
var startMock = new Mock<IHttpResponseStartFeature>();
|
||||||
|
startMock.Setup(o => o.StartAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
|
||||||
|
features.Set(startMock.Object);
|
||||||
|
|
||||||
|
var responseMock = new Mock<IHttpResponseFeature>();
|
||||||
|
responseMock.Setup(o => o.HasStarted).Returns(true);
|
||||||
|
features.Set(responseMock.Object);
|
||||||
|
|
||||||
|
var context = new DefaultHttpContext(features);
|
||||||
|
await context.Response.StartAsync();
|
||||||
|
|
||||||
|
startMock.Verify(m => m.StartAsync(default), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ResponseStart_CallsResponseBodyFlushIfNotSet()
|
public async Task ResponseStart_CallsResponseBodyFlushIfNotSet()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue