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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
// Don't poll if the transport task was canceled
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports
|
|||
catch (Exception ex)
|
||||
{
|
||||
Log.LongPollingTerminated(_logger, ex);
|
||||
context.Response.ContentType = "text/plain";
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.Http.Connections.Internal;
|
||||
using Microsoft.AspNetCore.Http.Connections.Internal.Transports;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Internal;
|
||||
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
|
||||
{
|
||||
protected override bool ShouldAccept => false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue