Merge branch 'benaadams/statemachines' into dev
This commit is contained in:
commit
706ff04160
|
|
@ -44,9 +44,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
protected readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders();
|
protected readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders();
|
||||||
private readonly FrameResponseHeaders _responseHeaders = new FrameResponseHeaders();
|
private readonly FrameResponseHeaders _responseHeaders = new FrameResponseHeaders();
|
||||||
|
|
||||||
private List<KeyValuePair<Func<object, Task>, object>> _onStarting;
|
protected List<KeyValuePair<Func<object, Task>, object>> _onStarting;
|
||||||
|
|
||||||
private List<KeyValuePair<Func<object, Task>, object>> _onCompleted;
|
protected List<KeyValuePair<Func<object, Task>, object>> _onCompleted;
|
||||||
|
|
||||||
private bool _requestProcessingStarted;
|
private bool _requestProcessingStarted;
|
||||||
private Task _requestProcessingTask;
|
private Task _requestProcessingTask;
|
||||||
|
|
@ -144,8 +144,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
// If a request abort token was previously explicitly set, return it.
|
// If a request abort token was previously explicitly set, return it.
|
||||||
if (_manuallySetRequestAbortToken.HasValue)
|
if (_manuallySetRequestAbortToken.HasValue)
|
||||||
|
{
|
||||||
return _manuallySetRequestAbortToken.Value;
|
return _manuallySetRequestAbortToken.Value;
|
||||||
|
}
|
||||||
// Otherwise, get the abort CTS. If we have one, which would mean that someone previously
|
// Otherwise, get the abort CTS. If we have one, which would mean that someone previously
|
||||||
// asked for the RequestAborted token, simply return its token. If we don't,
|
// asked for the RequestAborted token, simply return its token. If we don't,
|
||||||
// check to see whether we've already aborted, in which case just return an
|
// check to see whether we've already aborted, in which case just return an
|
||||||
|
|
@ -416,7 +417,28 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
|
public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!_responseStarted)
|
||||||
|
{
|
||||||
|
return WriteAsyncAwaited(data, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_autoChunk)
|
||||||
|
{
|
||||||
|
if (data.Count == 0)
|
||||||
|
{
|
||||||
|
return TaskUtilities.CompletedTask;
|
||||||
|
}
|
||||||
|
return WriteChunkedAsync(data, cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SocketOutput.WriteAsync(data, immediate: true, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task WriteAsyncAwaited(ArraySegment<byte> data, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await ProduceStartAndFireOnStarting(immediate: false);
|
await ProduceStartAndFireOnStarting(immediate: false);
|
||||||
|
|
||||||
|
|
@ -501,10 +523,27 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ProduceStartAndFireOnStarting(bool immediate = true)
|
public Task ProduceStartAndFireOnStarting(bool immediate = true)
|
||||||
{
|
{
|
||||||
if (_responseStarted) return;
|
if (_responseStarted) return TaskUtilities.CompletedTask;
|
||||||
|
|
||||||
|
if (_onStarting != null)
|
||||||
|
{
|
||||||
|
return FireOnStartingProduceStart(immediate: immediate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_applicationException != null)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(
|
||||||
|
"The response has been aborted due to an unhandled application exception.",
|
||||||
|
_applicationException);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProduceStart(immediate, appCompleted: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FireOnStartingProduceStart(bool immediate)
|
||||||
|
{
|
||||||
await FireOnStarting();
|
await FireOnStarting();
|
||||||
|
|
||||||
if (_applicationException != null)
|
if (_applicationException != null)
|
||||||
|
|
@ -527,7 +566,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
return CreateResponseHeader(statusBytes, appCompleted, immediate);
|
return CreateResponseHeader(statusBytes, appCompleted, immediate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task ProduceEnd()
|
protected Task ProduceEnd()
|
||||||
{
|
{
|
||||||
if (_applicationException != null)
|
if (_applicationException != null)
|
||||||
{
|
{
|
||||||
|
|
@ -535,7 +574,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
// We can no longer respond with a 500, so we simply close the connection.
|
// We can no longer respond with a 500, so we simply close the connection.
|
||||||
_requestProcessingStopping = true;
|
_requestProcessingStopping = true;
|
||||||
return;
|
return TaskUtilities.CompletedTask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -547,8 +586,26 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!_responseStarted)
|
||||||
|
{
|
||||||
|
return ProduceEndAwaited();
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteSuffix();
|
||||||
|
|
||||||
|
return TaskUtilities.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProduceEndAwaited()
|
||||||
|
{
|
||||||
await ProduceStart(immediate: true, appCompleted: true);
|
await ProduceStart(immediate: true, appCompleted: true);
|
||||||
|
|
||||||
|
WriteSuffix();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteSuffix()
|
||||||
|
{
|
||||||
// _autoChunk should be checked after we are sure ProduceStart() has been called
|
// _autoChunk should be checked after we are sure ProduceStart() has been called
|
||||||
// since ProduceStart() may set _autoChunk to true.
|
// since ProduceStart() may set _autoChunk to true.
|
||||||
if (_autoChunk)
|
if (_autoChunk)
|
||||||
|
|
|
||||||
|
|
@ -40,28 +40,27 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var terminated = false;
|
while (!_requestProcessingStopping)
|
||||||
while (!terminated && !_requestProcessingStopping)
|
|
||||||
{
|
{
|
||||||
while (!terminated && !_requestProcessingStopping && !TakeStartLine(SocketInput))
|
while (!_requestProcessingStopping && !TakeStartLine(SocketInput))
|
||||||
{
|
{
|
||||||
terminated = SocketInput.RemoteIntakeFin;
|
if (SocketInput.RemoteIntakeFin)
|
||||||
if (!terminated)
|
|
||||||
{
|
{
|
||||||
await SocketInput;
|
return;
|
||||||
}
|
}
|
||||||
|
await SocketInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput, _requestHeaders))
|
while (!_requestProcessingStopping && !TakeMessageHeaders(SocketInput, _requestHeaders))
|
||||||
{
|
{
|
||||||
terminated = SocketInput.RemoteIntakeFin;
|
if (SocketInput.RemoteIntakeFin)
|
||||||
if (!terminated)
|
|
||||||
{
|
{
|
||||||
await SocketInput;
|
return;
|
||||||
}
|
}
|
||||||
|
await SocketInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!terminated && !_requestProcessingStopping)
|
if (!_requestProcessingStopping)
|
||||||
{
|
{
|
||||||
var messageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
|
var messageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
|
||||||
_keepAlive = messageBody.RequestKeepAlive;
|
_keepAlive = messageBody.RequestKeepAlive;
|
||||||
|
|
@ -89,12 +88,15 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
// already failed. If an OnStarting callback throws we can go through
|
// already failed. If an OnStarting callback throws we can go through
|
||||||
// our normal error handling in ProduceEnd.
|
// our normal error handling in ProduceEnd.
|
||||||
// https://github.com/aspnet/KestrelHttpServer/issues/43
|
// https://github.com/aspnet/KestrelHttpServer/issues/43
|
||||||
if (!_responseStarted && _applicationException == null)
|
if (!_responseStarted && _applicationException == null && _onStarting != null)
|
||||||
{
|
{
|
||||||
await FireOnStarting();
|
await FireOnStarting();
|
||||||
}
|
}
|
||||||
|
|
||||||
await FireOnCompleted();
|
if (_onCompleted != null)
|
||||||
|
{
|
||||||
|
await FireOnCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
_application.DisposeContext(context, _applicationException);
|
_application.DisposeContext(context, _applicationException);
|
||||||
|
|
||||||
|
|
@ -114,7 +116,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
_responseBody.StopAcceptingWrites();
|
_responseBody.StopAcceptingWrites();
|
||||||
}
|
}
|
||||||
|
|
||||||
terminated = !_keepAlive;
|
if (!_keepAlive)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue