Remove synchronous Write APIs (#1838)

This commit is contained in:
David Fowler 2017-05-15 19:04:04 -07:00 committed by GitHub
parent 9ab09dbe48
commit cf16d601d6
8 changed files with 24 additions and 130 deletions

View File

@ -503,64 +503,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
}
}
public void Flush()
{
InitializeResponse(0).GetAwaiter().GetResult();
Output.Flush();
}
public async Task FlushAsync(CancellationToken cancellationToken)
public async Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken))
{
await InitializeResponse(0);
await Output.FlushAsync(cancellationToken);
}
public void Write(ArraySegment<byte> data)
{
// For the first write, ensure headers are flushed if Write(Chunked) isn't called.
var firstWrite = !HasResponseStarted;
if (firstWrite)
{
InitializeResponse(data.Count).GetAwaiter().GetResult();
}
else
{
VerifyAndUpdateWrite(data.Count);
}
if (_canHaveBody)
{
if (_autoChunk)
{
if (data.Count == 0)
{
if (firstWrite)
{
Flush();
}
return;
}
WriteChunked(data);
}
else
{
CheckLastWrite();
Output.Write(data);
}
}
else
{
HandleNonBodyResponseWrite();
if (firstWrite)
{
Flush();
}
}
}
public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken = default(CancellationToken))
{
if (!HasResponseStarted)
{
@ -679,11 +628,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
}
}
private void WriteChunked(ArraySegment<byte> data)
{
Output.Write(data, chunk: true);
}
private Task WriteChunkedAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
{
return Output.WriteAsync(data, chunk: true, cancellationToken: cancellationToken);
@ -707,12 +651,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return;
}
StringValues expect;
if (_httpVersion == Http.HttpVersion.Http11 &&
RequestHeaders.TryGetValue("Expect", out expect) &&
RequestHeaders.TryGetValue("Expect", out var expect) &&
(expect.FirstOrDefault() ?? "").Equals("100-continue", StringComparison.OrdinalIgnoreCase))
{
Output.Write(_continueBytes);
Output.WriteAsync(_continueBytes).GetAwaiter().GetResult();
}
}

View File

@ -33,9 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public override void Flush()
{
ValidateState(default(CancellationToken));
_frameControl.Flush();
FlushAsync(default(CancellationToken)).GetAwaiter().GetResult();
}
public override Task FlushAsync(CancellationToken cancellationToken)
@ -60,9 +58,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public override void Write(byte[] buffer, int offset, int count)
{
ValidateState(default(CancellationToken));
_frameControl.Write(new ArraySegment<byte>(buffer, offset, count));
WriteAsync(buffer, offset, count, default(CancellationToken)).GetAwaiter().GetResult();
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)

View File

@ -10,9 +10,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public interface IFrameControl
{
void ProduceContinue();
void Write(ArraySegment<byte> data);
Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken);
void Flush();
Task FlushAsync(CancellationToken cancellationToken);
}
}

View File

@ -39,11 +39,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_flushCompleted = OnFlushCompleted;
}
public void Write(ArraySegment<byte> buffer, bool chunk = false)
{
WriteAsync(buffer, default(CancellationToken), chunk).GetAwaiter().GetResult();
}
public Task WriteAsync(ArraySegment<byte> buffer, bool chunk = false, CancellationToken cancellationToken = default(CancellationToken))
{
if (cancellationToken.IsCancellationRequested)
@ -54,11 +49,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return WriteAsync(buffer, cancellationToken, chunk);
}
public void Flush()
{
WriteAsync(_emptyData, default(CancellationToken)).GetAwaiter().GetResult();
}
public Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return WriteAsync(_emptyData, cancellationToken);

View File

@ -211,10 +211,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void ThrowsWhenStatusCodeIsSetAfterResponseStarted()
public async Task ThrowsWhenStatusCodeIsSetAfterResponseStarted()
{
// Act
_frame.Write(new ArraySegment<byte>(new byte[1]));
await _frame.WriteAsync(new ArraySegment<byte>(new byte[1]));
// Assert
Assert.True(_frame.HasResponseStarted);
@ -222,10 +222,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void ThrowsWhenReasonPhraseIsSetAfterResponseStarted()
public async Task ThrowsWhenReasonPhraseIsSetAfterResponseStarted()
{
// Act
_frame.Write(new ArraySegment<byte>(new byte[1]));
await _frame.WriteAsync(new ArraySegment<byte>(new byte[1]));
// Assert
Assert.True(_frame.HasResponseStarted);
@ -233,9 +233,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void ThrowsWhenOnStartingIsSetAfterResponseStarted()
public async Task ThrowsWhenOnStartingIsSetAfterResponseStarted()
{
_frame.Write(new ArraySegment<byte>(new byte[1]));
await _frame.WriteAsync(new ArraySegment<byte>(new byte[1]));
// Act/Assert
Assert.True(_frame.HasResponseStarted);
@ -472,13 +472,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void WriteThrowsForNonBodyResponse()
public async Task WriteThrowsForNonBodyResponse()
{
// Arrange
((IHttpResponseFeature)_frame).StatusCode = StatusCodes.Status304NotModified;
// Act/Assert
Assert.Throws<InvalidOperationException>(() => _frame.Write(new ArraySegment<byte>(new byte[1])));
await Assert.ThrowsAsync<InvalidOperationException>(() => _frame.WriteAsync(new ArraySegment<byte>(new byte[1])));
}
[Fact]
@ -493,14 +493,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void WriteDoesNotThrowForHeadResponse()
public async Task WriteDoesNotThrowForHeadResponse()
{
// Arrange
_frame.HttpVersion = "HTTP/1.1";
((IHttpRequestFeature)_frame).Method = "HEAD";
// Act/Assert
_frame.Write(new ArraySegment<byte>(new byte[1]));
await _frame.WriteAsync(new ArraySegment<byte>(new byte[1]));
}
[Fact]
@ -515,7 +515,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void ManuallySettingTransferEncodingThrowsForHeadResponse()
public async Task ManuallySettingTransferEncodingThrowsForHeadResponse()
{
// Arrange
_frame.HttpVersion = "HTTP/1.1";
@ -525,11 +525,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_frame.ResponseHeaders.Add("Transfer-Encoding", "chunked");
// Assert
Assert.Throws<InvalidOperationException>(() => _frame.Flush());
await Assert.ThrowsAsync<InvalidOperationException>(() => _frame.FlushAsync());
}
[Fact]
public void ManuallySettingTransferEncodingThrowsForNoBodyResponse()
public async Task ManuallySettingTransferEncodingThrowsForNoBodyResponse()
{
// Arrange
_frame.HttpVersion = "HTTP/1.1";
@ -539,7 +539,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_frame.ResponseHeaders.Add("Transfer-Encoding", "chunked");
// Assert
Assert.Throws<InvalidOperationException>(() => _frame.Flush());
await Assert.ThrowsAsync<InvalidOperationException>(() => _frame.FlushAsync());
}
[Fact]
@ -558,7 +558,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void RequestAbortedTokenIsResetBeforeLastWriteWithContentLength()
public async Task RequestAbortedTokenIsResetBeforeLastWriteWithContentLength()
{
_frame.ResponseHeaders["Content-Length"] = "12";
@ -567,11 +567,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
foreach (var ch in "hello, worl")
{
_frame.Write(new ArraySegment<byte>(new[] { (byte)ch }));
await _frame.WriteAsync(new ArraySegment<byte>(new[] { (byte)ch }));
Assert.Same(original, _frame.RequestAborted.WaitHandle);
}
_frame.Write(new ArraySegment<byte>(new[] { (byte)'d' }));
await _frame.WriteAsync(new ArraySegment<byte>(new[] { (byte)'d' }));
Assert.NotSame(original, _frame.RequestAborted.WaitHandle);
}

View File

@ -11,10 +11,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests.TestHelpers
{
public class MockFrameControl : IFrameControl
{
public void Flush()
{
}
public Task FlushAsync(CancellationToken cancellationToken)
{
return TaskCache.CompletedTask;
@ -24,10 +20,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests.TestHelpers
{
}
public void Write(ArraySegment<byte> data)
{
}
public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
{
return TaskCache.CompletedTask;

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
FrameContext.FrameControl = this;
}
public IPipe Pipe { get; }
public IPipe Pipe { get; }
public Frame FrameContext { get; set; }
@ -70,23 +70,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
}
void IFrameControl.ProduceContinue()
{
}
void IFrameControl.Write(ArraySegment<byte> data)
{
}
Task IFrameControl.WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
{
return TaskCache.CompletedTask;
}
void IFrameControl.Flush()
{
}
Task IFrameControl.FlushAsync(CancellationToken cancellationToken)
{
return TaskCache.CompletedTask;

View File

@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
using Microsoft.AspNetCore.Server.Kestrel.Performance.Mocks;
using Microsoft.AspNetCore.Testing;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
@ -38,18 +37,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
_frameChunked.RequestHeaders.Add("Transfer-Encoding", "chunked");
}
[Benchmark]
public void Write()
{
_frame.Write(new ArraySegment<byte>(_writeData));
}
[Benchmark]
public void WriteChunked()
{
_frameChunked.Write(new ArraySegment<byte>(_writeData));
}
[Benchmark]
public async Task WriteAsync()
{