Skip to content

Commit 50048e0

Browse files
authored
Ensure PipeWriter is flushed (#485)
1 parent b4ab598 commit 50048e0

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Features/HttpResponseAdapterFeature.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ bool IHttpResponseBufferingFeature.IsEnabled
9595

9696
private async ValueTask FlushInternalAsync()
9797
{
98+
if (_pipeWriter is { })
99+
{
100+
await _pipeWriter.FlushAsync();
101+
}
102+
98103
if (_state is StreamState.Buffering && _bufferedStream is not null && !SuppressContent)
99104
{
100105
if (_filter is { } filter)
@@ -115,7 +120,23 @@ private async ValueTask FlushInternalAsync()
115120

116121
Stream IHttpResponseBodyFeature.Stream => this;
117122

118-
PipeWriter IHttpResponseBodyFeature.Writer => _pipeWriter ??= PipeWriter.Create(this, new StreamPipeWriterOptions(leaveOpen: true));
123+
PipeWriter IHttpResponseBodyFeature.Writer
124+
{
125+
get
126+
{
127+
if (_pipeWriter is null)
128+
{
129+
_pipeWriter = PipeWriter.Create(this, new StreamPipeWriterOptions(leaveOpen: true));
130+
131+
if (_state is StreamState.Complete)
132+
{
133+
_pipeWriter.Complete();
134+
}
135+
}
136+
137+
return _pipeWriter;
138+
}
139+
}
119140

120141
public bool SuppressContent
121142
{
@@ -233,6 +254,11 @@ private async Task CompleteAsync()
233254

234255
_state = StreamState.Complete;
235256

257+
if (_pipeWriter is { })
258+
{
259+
await _pipeWriter.CompleteAsync();
260+
}
261+
236262
await _responseBodyFeature.CompleteAsync();
237263
}
238264

test/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests/ResponseStreamTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Buffers;
56
using System.Collections.Generic;
67
using System.IO;
78
using System.Text;
@@ -44,6 +45,32 @@ public async Task BufferedOutputIsFlushed()
4445
Assert.Equal(ContentValue, result);
4546
}
4647

48+
[Fact]
49+
public async Task OutputPipeIsFlushed()
50+
{
51+
const string Message = "hello world from pipe!";
52+
53+
var result = await RunAsync(context =>
54+
{
55+
context.AsAspNetCore().Response.BodyWriter.Write(Encoding.UTF8.GetBytes(Message));
56+
});
57+
58+
Assert.Equal(Message, result);
59+
}
60+
61+
[Fact]
62+
public async Task OutputPipeIsMarkedCompleteIfRequestIsComplete()
63+
{
64+
var result = await RunAsync(async context =>
65+
{
66+
await context.AsAspNetCore().Response.CompleteAsync();
67+
68+
Assert.Throws<InvalidOperationException>(() => context.AsAspNetCore().Response.BodyWriter.Write("Hello world"u8));
69+
});
70+
71+
Assert.Empty(result);
72+
}
73+
4774
[Fact]
4875
public async Task BufferedOutputIsFlushedOnceWithStart()
4976
{

0 commit comments

Comments
 (0)