Skip to content

Commit

Permalink
NLogRequestPostedBodyMiddleware - Fixed handling of Stream.CanSeek (#958
Browse files Browse the repository at this point in the history
)
  • Loading branch information
snakefoot authored Jun 30, 2023
1 parent 737ca2a commit 307bdb4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 11 deletions.
12 changes: 9 additions & 3 deletions src/NLog.Web.AspNetCore/NLogRequestPostedBodyMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,9 @@ 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");
InternalLogger.Debug("NLogRequestPostedBodyMiddleware: HttpContext.Request.Body stream position non-zero");
return false;
}

Expand All @@ -116,6 +115,13 @@ private bool ShouldCaptureRequestBody(HttpContext context)
/// <returns>The contents of the Stream read fully from start to end as a String</returns>
private static async Task<string> 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -65,7 +66,6 @@ public void EmptyBodyTest()
// Assert
Assert.NotNull(defaultContext.Items);
Assert.Empty(defaultContext.Items);
Assert.Null(defaultContext.Items[AspNetRequestPostedBodyLayoutRenderer.NLogPostedRequestBodyKey]);
}

[Fact]
Expand All @@ -86,7 +86,6 @@ public void ExcludContentTypeTest()
// Assert
Assert.NotNull(defaultContext.Items);
Assert.Empty(defaultContext.Items);
Assert.Null(defaultContext.Items[AspNetRequestPostedBodyLayoutRenderer.NLogPostedRequestBodyKey]);
}

[Fact]
Expand Down Expand Up @@ -203,21 +202,67 @@ public void CannotSeekLengthTest()
// Arrange
DefaultHttpContext defaultContext = new DefaultHttpContext();

defaultContext.Request.Body = Substitute.For<Stream>();
defaultContext.Request.ContentLength = 1;
defaultContext.Request.Body = new NetworkStream() { _length = 2 };
defaultContext.Request.ContentLength = 2;
defaultContext.Request.ContentType = "text/plain";

defaultContext.Request.Body.CanRead.Returns(true);
defaultContext.Request.Body.CanSeek.Returns(false);

// 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 = new NetworkStream() { _length = 2, Position = 2 };
defaultContext.Request.ContentLength = 2;
defaultContext.Request.ContentType = "text/plain";

// Act
var middlewareInstance =
new NLogRequestPostedBodyMiddleware(Next, NLogRequestPostedBodyMiddlewareOptions.Default);
middlewareInstance.Invoke(defaultContext).ConfigureAwait(false).GetAwaiter().GetResult();

// Assert
Assert.NotNull(defaultContext.Items);
Assert.Empty(defaultContext.Items);
}

private sealed class NetworkStream : Stream
{
internal long _length;

public override bool CanRead => true;

public override bool CanSeek => false;

public override bool CanWrite => false;

public override long Length => _length;

public override long Position { get; set; }

public override int Read(byte[] buffer, int offset, int count)
{
int delta = Math.Min((int)(Length - Position), count);
Position += delta;
return delta;
}

public override long Seek(long offset, SeekOrigin origin) => throw new System.NotSupportedException();
public override void SetLength(long value) => throw new System.NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new System.NotSupportedException();
public override void Flush() => throw new System.NotSupportedException();
}
}
}

0 comments on commit 307bdb4

Please sign in to comment.