Skip to content

Commit 48261fd

Browse files
authored
Undo use of pipewriter in FileBufferingWriteStream (#21833)
1 parent 0e652d1 commit 48261fd

File tree

7 files changed

+30
-29
lines changed

7 files changed

+30
-29
lines changed

src/Http/WebUtilities/ref/Microsoft.AspNetCore.WebUtilities.netcoreapp.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ protected override void Dispose(bool disposing) { }
7777
[System.Diagnostics.DebuggerStepThroughAttribute]
7878
public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
7979
[System.Diagnostics.DebuggerStepThroughAttribute]
80-
public System.Threading.Tasks.Task DrainBufferAsync(System.IO.Pipelines.PipeWriter destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
81-
[System.Diagnostics.DebuggerStepThroughAttribute]
8280
public System.Threading.Tasks.Task DrainBufferAsync(System.IO.Stream destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
8381
public override void Flush() { }
8482
public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }

src/Http/WebUtilities/src/FileBufferingWriteStream.cs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -186,25 +186,8 @@ public async Task DrainBufferAsync(Stream destination, CancellationToken cancell
186186
// unspooled content. Copy the FileStream content first when available.
187187
if (FileStream != null)
188188
{
189-
// We make a new stream for async reads from disk and async writes to the destination
190-
await using var readStream = new FileStream(FileStream.Name, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite, bufferSize: 1, useAsync: true);
191-
192-
await readStream.CopyToAsync(destination, cancellationToken);
193-
194-
// This is created with delete on close
195-
await FileStream.DisposeAsync();
196-
FileStream = null;
197-
}
189+
await FileStream.FlushAsync(cancellationToken);
198190

199-
await PagedByteBuffer.MoveToAsync(destination, cancellationToken);
200-
}
201-
202-
public async Task DrainBufferAsync(PipeWriter destination, CancellationToken cancellationToken = default)
203-
{
204-
// When not null, FileStream always has "older" spooled content. The PagedByteBuffer always has "newer"
205-
// unspooled content. Copy the FileStream content first when available.
206-
if (FileStream != null)
207-
{
208191
// We make a new stream for async reads from disk and async writes to the destination
209192
await using var readStream = new FileStream(FileStream.Name, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite, bufferSize: 1, useAsync: true);
210193

src/Http/WebUtilities/test/FileBufferingWriteStreamTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,24 @@ public async Task DrainBufferAsync_WithContentInDisk_CopiesContentFromMemoryStre
371371
Assert.Equal(0, bufferingStream.Length);
372372
}
373373

374+
[Fact]
375+
public async Task DrainBufferAsync_IncludesContentPossiblyBufferedByFileStream()
376+
{
377+
// We want to ensure that the FileStream (which has a 1-byte buffer) flushes prior to the other read stream reading input.
378+
// Arrange
379+
var input = new byte[] { 3, };
380+
using var bufferingStream = new FileBufferingWriteStream(0, tempFileDirectoryAccessor: () => TempDirectory);
381+
bufferingStream.Write(input, 0, input.Length);
382+
var memoryStream = new MemoryStream();
383+
384+
// Act
385+
await bufferingStream.DrainBufferAsync(memoryStream, default);
386+
387+
// Assert
388+
Assert.Equal(input, memoryStream.ToArray());
389+
Assert.Equal(0, bufferingStream.Length);
390+
}
391+
374392
public void Dispose()
375393
{
376394
try

src/Mvc/Mvc.Formatters.Xml/src/XmlSerializerOutputFormatter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext co
261261
if (fileBufferingWriteStream != null)
262262
{
263263
response.ContentLength = fileBufferingWriteStream.Length;
264-
await fileBufferingWriteStream.DrainBufferAsync(response.BodyWriter);
264+
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
265265
}
266266
}
267267
finally

src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext co
155155
if (fileBufferingWriteStream != null)
156156
{
157157
response.ContentLength = fileBufferingWriteStream.Length;
158-
await fileBufferingWriteStream.DrainBufferAsync(response.BodyWriter);
158+
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
159159
}
160160
}
161161
finally

src/Mvc/test/Mvc.FunctionalTests/JsonOutputFormatterTestBase.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,17 @@ public virtual async Task Formatting_DictionaryType()
154154
Assert.Equal(expected, await response.Content.ReadAsStringAsync());
155155
}
156156

157-
[Fact]
158-
public virtual async Task Formatting_LargeObject()
157+
[Theory]
158+
[InlineData(65 * 1024)]
159+
[InlineData(2 * 1024 * 1024)]
160+
public virtual async Task Formatting_LargeObject(int size)
159161
{
160162
// Arrange
161-
var expectedName = "This is long so we can test large objects " + new string('a', 1024 * 65);
163+
var expectedName = "This is long so we can test large objects " + new string('a', size);
162164
var expected = $"{{\"id\":10,\"name\":\"{expectedName}\",\"streetName\":null}}";
163165

164166
// Act
165-
var response = await Client.GetAsync($"/JsonOutputFormatter/{nameof(JsonOutputFormatterController.LargeObjectResult)}");
167+
var response = await Client.GetAsync($"/JsonOutputFormatter/{nameof(JsonOutputFormatterController.LargeObjectResult)}/{size}");
166168

167169
// Assert
168170
await response.AssertStatusCodeAsync(HttpStatusCode.OK);

src/Mvc/test/WebSites/FormatterWebSite/Controllers/JsonOutputFormatterController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ public ActionResult<Dictionary<string, string>> DictionaryResult() =>
4444
["Key3"] = null,
4545
};
4646

47-
[HttpGet]
48-
public ActionResult<SimpleModel> LargeObjectResult() =>
47+
[HttpGet("{size:int}")]
48+
public ActionResult<SimpleModel> LargeObjectResult(int size) =>
4949
new SimpleModel
5050
{
5151
Id = 10,
52-
Name = "This is long so we can test large objects " + new string('a', 1024 * 65),
52+
Name = "This is long so we can test large objects " + new string('a', size),
5353
};
5454

5555
[HttpGet]

0 commit comments

Comments
 (0)