diff --git a/src/NLog.Web.AspNetCore/NLogRequestPostedBodyMiddleware.cs b/src/NLog.Web.AspNetCore/NLogRequestPostedBodyMiddleware.cs index 1b6972da..a567d3c6 100644 --- a/src/NLog.Web.AspNetCore/NLogRequestPostedBodyMiddleware.cs +++ b/src/NLog.Web.AspNetCore/NLogRequestPostedBodyMiddleware.cs @@ -97,8 +97,7 @@ private bool ShouldCaptureRequestBody(HttpContext context) return false; } - // If we cannot seek the stream we cannot capture the body - if (!postedBody.CanSeek) + if (postedBody.Position != 0 && !postedBody.CanSeek) { InternalLogger.Debug("NLogRequestPostedBodyMiddleware: HttpContext.Request.Body stream is non-seekable"); return false; @@ -116,6 +115,13 @@ private bool ShouldCaptureRequestBody(HttpContext context) /// The contents of the Stream read fully from start to end as a String private static async Task GetString(Stream stream) { + // If we cannot seek the stream we cannot capture the body + if (!stream.CanSeek) + { + InternalLogger.Debug("NLogRequestPostedBodyMiddleware: HttpContext.Request.Body stream is non-seekable"); + return string.Empty; + } + string responseText = null; // Save away the original stream position diff --git a/tests/NLog.Web.AspNetCore.Tests/NLogRequestPostedBodyMiddlewareTests.cs b/tests/NLog.Web.AspNetCore.Tests/NLogRequestPostedBodyMiddlewareTests.cs index 57ce7fa8..5b5d2891 100644 --- a/tests/NLog.Web.AspNetCore.Tests/NLogRequestPostedBodyMiddlewareTests.cs +++ b/tests/NLog.Web.AspNetCore.Tests/NLogRequestPostedBodyMiddlewareTests.cs @@ -65,7 +65,6 @@ public void EmptyBodyTest() // Assert Assert.NotNull(defaultContext.Items); Assert.Empty(defaultContext.Items); - Assert.Null(defaultContext.Items[AspNetRequestPostedBodyLayoutRenderer.NLogPostedRequestBodyKey]); } [Fact] @@ -86,7 +85,6 @@ public void ExcludContentTypeTest() // Assert Assert.NotNull(defaultContext.Items); Assert.Empty(defaultContext.Items); - Assert.Null(defaultContext.Items[AspNetRequestPostedBodyLayoutRenderer.NLogPostedRequestBodyKey]); } [Fact] @@ -204,17 +202,51 @@ public void CannotSeekLengthTest() DefaultHttpContext defaultContext = new DefaultHttpContext(); defaultContext.Request.Body = Substitute.For(); - defaultContext.Request.ContentLength = 1; + defaultContext.Request.ContentLength = 2; defaultContext.Request.ContentType = "text/plain"; defaultContext.Request.Body.CanRead.Returns(true); defaultContext.Request.Body.CanSeek.Returns(false); + defaultContext.Request.Body.Length.Returns(2); + int firstCall = 2; + defaultContext.Request.Body.Read(default, default, default).ReturnsForAnyArgs(x => --firstCall); + defaultContext.Request.Body.ReadAsync(default, default, default).ReturnsForAnyArgs(x => --firstCall); // Act var middlewareInstance = new NLogRequestPostedBodyMiddleware(Next,NLogRequestPostedBodyMiddlewareOptions.Default); middlewareInstance.Invoke(defaultContext).ConfigureAwait(false).GetAwaiter().GetResult(); + // Assert + Assert.NotNull(defaultContext.Items); + Assert.Single(defaultContext.Items); + Assert.NotNull(defaultContext.Items[AspNetRequestPostedBodyLayoutRenderer.NLogPostedRequestBodyKey]); + Assert.True(defaultContext.Items[AspNetRequestPostedBodyLayoutRenderer.NLogPostedRequestBodyKey] is string); + } + + [Fact] + public void CannotSeekLengthAndStartedTest() + { + // Arrange + DefaultHttpContext defaultContext = new DefaultHttpContext(); + + defaultContext.Request.Body = Substitute.For(); + defaultContext.Request.ContentLength = 2; + defaultContext.Request.ContentType = "text/plain"; + + defaultContext.Request.Body.CanRead.Returns(true); + defaultContext.Request.Body.CanSeek.Returns(false); + defaultContext.Request.Body.Position.Returns(1); // Started + defaultContext.Request.Body.Length.Returns(2); + int firstCall = 2; + defaultContext.Request.Body.Read(default, default, default).ReturnsForAnyArgs(x => --firstCall); + defaultContext.Request.Body.ReadAsync(default, default, default).ReturnsForAnyArgs(x => --firstCall); + + // Act + var middlewareInstance = + new NLogRequestPostedBodyMiddleware(Next, NLogRequestPostedBodyMiddlewareOptions.Default); + middlewareInstance.Invoke(defaultContext).ConfigureAwait(false).GetAwaiter().GetResult(); + // Assert Assert.NotNull(defaultContext.Items); Assert.Empty(defaultContext.Items);