Close LongPolling connection on poll exception (#2701)
This commit is contained in:
parent
25b826de75
commit
3d6e1e69fd
|
|
@ -289,6 +289,13 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal
|
||||||
pollAgain = false;
|
pollAgain = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (resultTask.IsFaulted)
|
||||||
|
{
|
||||||
|
// transport task was faulted, we should remove the connection
|
||||||
|
await _manager.DisposeAndRemoveAsync(connection, closeGracefully: false);
|
||||||
|
|
||||||
|
pollAgain = false;
|
||||||
|
}
|
||||||
else if (context.Response.StatusCode == StatusCodes.Status204NoContent)
|
else if (context.Response.StatusCode == StatusCodes.Status204NoContent)
|
||||||
{
|
{
|
||||||
// Don't poll if the transport task was canceled
|
// Don't poll if the transport task was canceled
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.LongPollingTerminated(_logger, ex);
|
Log.LongPollingTerminated(_logger, ex);
|
||||||
|
context.Response.ContentType = "text/plain";
|
||||||
|
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
using Microsoft.AspNetCore.Connections.Features;
|
using Microsoft.AspNetCore.Connections.Features;
|
||||||
using Microsoft.AspNetCore.Http.Connections.Internal;
|
using Microsoft.AspNetCore.Http.Connections.Internal;
|
||||||
|
using Microsoft.AspNetCore.Http.Connections.Internal.Transports;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Http.Internal;
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests;
|
using Microsoft.AspNetCore.SignalR.Tests;
|
||||||
|
|
@ -2016,6 +2017,48 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ErrorDuringPollWillCloseConnection()
|
||||||
|
{
|
||||||
|
bool ExpectedErrors(WriteContext writeContext)
|
||||||
|
{
|
||||||
|
return (writeContext.LoggerName == typeof(LongPollingTransport).FullName &&
|
||||||
|
writeContext.EventId.Name == "LongPollingTerminated") ||
|
||||||
|
(writeContext.LoggerName == typeof(HttpConnectionManager).FullName &&
|
||||||
|
writeContext.EventId.Name == "FailedDispose");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug, expectedErrorsFilter: ExpectedErrors))
|
||||||
|
{
|
||||||
|
var manager = CreateConnectionManager(loggerFactory);
|
||||||
|
var connection = manager.CreateConnection();
|
||||||
|
connection.TransportType = HttpTransportType.LongPolling;
|
||||||
|
|
||||||
|
var dispatcher = new HttpConnectionDispatcher(manager, loggerFactory);
|
||||||
|
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddSingleton<TestConnectionHandler>();
|
||||||
|
var builder = new ConnectionBuilder(services.BuildServiceProvider());
|
||||||
|
builder.UseConnectionHandler<TestConnectionHandler>();
|
||||||
|
var app = builder.Build();
|
||||||
|
var options = new HttpConnectionDispatcherOptions();
|
||||||
|
|
||||||
|
var context = MakeRequest("/foo", connection);
|
||||||
|
|
||||||
|
// Initial poll will complete immediately
|
||||||
|
await dispatcher.ExecuteAsync(context, options, app).OrTimeout();
|
||||||
|
|
||||||
|
var pollContext = MakeRequest("/foo", connection);
|
||||||
|
var pollTask = dispatcher.ExecuteAsync(pollContext, options, app);
|
||||||
|
// fail LongPollingTransport ReadAsync
|
||||||
|
connection.Transport.Output.Complete(new InvalidOperationException());
|
||||||
|
await pollTask.OrTimeout();
|
||||||
|
|
||||||
|
Assert.Equal(StatusCodes.Status500InternalServerError, pollContext.Response.StatusCode);
|
||||||
|
Assert.False(manager.TryGetConnection(connection.ConnectionId, out var _));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class RejectHandler : TestAuthenticationHandler
|
private class RejectHandler : TestAuthenticationHandler
|
||||||
{
|
{
|
||||||
protected override bool ShouldAccept => false;
|
protected override bool ShouldAccept => false;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue