Remove synchronous Write APIs (#1838)
This commit is contained in:
parent
9ab09dbe48
commit
cf16d601d6
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue