Handle incoming HTTP requests being canceled gracefully (#2314)
This commit is contained in:
parent
bff2060454
commit
96bbe70cd8
|
|
@ -49,6 +49,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal
|
|||
private static readonly Action<ILogger, string, Exception> _connectionDisposedWhileWriteInProgress =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(13, "ConnectionDisposedWhileWriteInProgress"), "Connection {TransportConnectionId} was disposed while a write was in progress.");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _failedToReadHttpRequestBody =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(14, "FailedToReadHttpRequestBody"), "Connection {TransportConnectionId} failed to read the HTTP request body.");
|
||||
|
||||
public static void ConnectionDisposed(ILogger logger, string connectionId)
|
||||
{
|
||||
_connectionDisposed(logger, connectionId, null);
|
||||
|
|
@ -113,6 +116,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal
|
|||
{
|
||||
_connectionDisposedWhileWriteInProgress(logger, connectionId, ex);
|
||||
}
|
||||
|
||||
public static void FailedToReadHttpRequestBody(ILogger logger, string connectionId, Exception ex)
|
||||
{
|
||||
_failedToReadHttpRequestBody(logger, connectionId, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,6 +505,15 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal
|
|||
context.Response.ContentType = "text/plain";
|
||||
return;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Can occur when the HTTP request is canceled by the client
|
||||
Log.FailedToReadHttpRequestBody(_logger, connection.ConnectionId, ex);
|
||||
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
context.Response.ContentType = "text/plain";
|
||||
return;
|
||||
}
|
||||
|
||||
Log.ReceivedBytes(_logger, connection.ApplicationStream.Length);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
|
|
@ -719,6 +720,44 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(HttpTransportType.LongPolling)]
|
||||
[InlineData(HttpTransportType.ServerSentEvents)]
|
||||
public async Task IOExceptionWhenReadingRequestReturns400Response(HttpTransportType transportType)
|
||||
{
|
||||
using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug))
|
||||
{
|
||||
var manager = CreateConnectionManager(loggerFactory);
|
||||
var dispatcher = new HttpConnectionDispatcher(manager, loggerFactory);
|
||||
var connection = manager.CreateConnection();
|
||||
connection.TransportType = transportType;
|
||||
|
||||
var mockStream = new Mock<Stream>();
|
||||
mockStream.Setup(m => m.CopyToAsync(It.IsAny<Stream>(), It.IsAny<int>(), It.IsAny<CancellationToken>())).Throws(new IOException());
|
||||
|
||||
using (var responseBody = new MemoryStream())
|
||||
{
|
||||
var context = new DefaultHttpContext();
|
||||
context.Request.Body = mockStream.Object;
|
||||
context.Response.Body = responseBody;
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<TestConnectionHandler>();
|
||||
services.AddOptions();
|
||||
context.Request.Path = "/foo";
|
||||
context.Request.Method = "POST";
|
||||
var values = new Dictionary<string, StringValues>();
|
||||
values["id"] = connection.ConnectionId;
|
||||
var qs = new QueryCollection(values);
|
||||
context.Request.Query = qs;
|
||||
|
||||
await dispatcher.ExecuteAsync(context, new HttpConnectionDispatcherOptions(), c => Task.CompletedTask);
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EndpointsThatRequireConnectionId400WhenNoConnectionIdProvidedForPost()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue