Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added layoutrenderer aspnet-request-has-posted-body and aspnet-request-stream-id #845

Merged
merged 20 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#if NET5_0_OR_GREATER
using NLog.LayoutRenderers;
using NLog.Web.Internal;
using System.Text;
using Microsoft.AspNetCore.Http.Features;

namespace NLog.Web.LayoutRenderers
{
/// <summary>
/// Used to indicate if the request has a body.
/// Uses IHttpRequestBodyDetectionFeature
///
/// This returns true when:
/// - It's an HTTP/1.x request with a non-zero Content-Length or a 'Transfer-Encoding: chunked' header.
/// - It's an HTTP/2 request that did not set the END_STREAM flag on the initial headers frame.
/// The final request body length may still be zero for the chunked or HTTP/2 scenarios.
///
/// This returns false when:
/// - It's an HTTP/1.x request with no Content-Length or 'Transfer-Encoding: chunked' header, or the Content-Length is 0.
/// - It's an HTTP/1.x request with Connection: Upgrade(e.g.WebSockets).
/// There is no HTTP request body for these requests and no data should be received until after the upgrade.
/// - It's an HTTP/2 request that set END_STREAM on the initial headers frame. When false, the request body should never return data.
/// </summary>
/// <remarks>
/// <code>${aspnet-request-has-body}</code>
/// </remarks>
[LayoutRenderer("aspnet-request-has-body")]
public class AspNetRequestHasBodyLayoutRenderer : AspNetLayoutRendererBase
{
/// <inheritdoc/>
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
{
var features = HttpContextAccessor.HttpContext.TryGetFeatureCollection();
var value = features?.Get<IHttpRequestBodyDetectionFeature>()?.CanHaveBody ?? false;
builder.Append(value ? '1' : '0');
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if NET5_0_OR_GREATER
using System.Text;
using Microsoft.AspNetCore.Connections.Features;
using NLog.LayoutRenderers;
using NLog.Web.Internal;

namespace NLog.Web.LayoutRenderers
{
/// <summary>
/// Represents the long int identifier for the stream.
/// Uses IStreamIdFeature
///
/// This will inform when the connection is being reused, or when the connection has been closed and reopened,
/// based on when the value stays or same, or changes.
/// </summary>
/// <remarks>
/// <code>${aspnet-request-stream-id}</code>
/// </remarks>
[LayoutRenderer("aspnet-request-stream-id")]
public class AspNetRequestStreamIdLayoutRenderer : AspNetLayoutRendererBase
snakefoot marked this conversation as resolved.
Show resolved Hide resolved
{
/// <inheritdoc/>
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
{
var features = HttpContextAccessor.HttpContext.TryGetFeatureCollection();
var streamIdFeature = features?.Get<IStreamIdFeature>();
builder.Append(streamIdFeature?.StreamId);
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#if NET5_0_OR_GREATER
using NLog.Web.LayoutRenderers;
using Microsoft.AspNetCore.Http.Features;
using NSubstitute;
using Xunit;

namespace NLog.Web.Tests.LayoutRenderers
{
public class AspNetRequestHasBodyLayoutRendererTests : LayoutRenderersTestBase<AspNetRequestHasBodyLayoutRenderer>
{
[Fact]
public void TrueTest()
{
// Arrange
var (renderer, httpContext) = CreateWithHttpContext();

var bodyDetectionFeature = Substitute.For<IHttpRequestBodyDetectionFeature>();
bodyDetectionFeature.CanHaveBody.Returns(true);

var featureCollection = new FeatureCollection();
featureCollection.Set<IHttpRequestBodyDetectionFeature>(bodyDetectionFeature);

httpContext.Features.Returns(featureCollection);
// Act
var result = renderer.Render(new LogEventInfo());
// Assert
Assert.Equal("1", result);
}

[Fact]
public void FalseTest()
{
// Arrange
var (renderer, httpContext) = CreateWithHttpContext();

var bodyDetectionFeature = Substitute.For<IHttpRequestBodyDetectionFeature>();
bodyDetectionFeature.CanHaveBody.Returns(false);

var featureCollection = new FeatureCollection();
featureCollection.Set<IHttpRequestBodyDetectionFeature>(bodyDetectionFeature);

httpContext.Features.Returns(featureCollection);
// Act
var result = renderer.Render(new LogEventInfo());
// Assert
Assert.Equal("0", result);
}

[Fact]
public void NullTest()
{
// Arrange
var (renderer, httpContext) = CreateWithHttpContext();

httpContext.Features.Returns(new FeatureCollection());
// Act
var result = renderer.Render(new LogEventInfo());
// Assert
Assert.Equal("0", result);
}

protected override void NullRendersEmptyString()
{
// Arrange
var (renderer, _) = CreateWithHttpContext();

// Act
string result = renderer.Render(LogEventInfo.CreateNullEvent());

// Assert
Assert.Equal("0", result);
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#if NET5_0_OR_GREATER
using NLog.Web.LayoutRenderers;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http.Features;
using NSubstitute;
using Xunit;

namespace NLog.Web.Tests.LayoutRenderers
{
public class AspNetRequestStreamIdLayoutRendererTests : LayoutRenderersTestBase<AspNetRequestStreamIdLayoutRenderer>
{
[Fact]
public void SuccessTest()
{
// Arrange
var (renderer, httpContext) = CreateWithHttpContext();
var streamIdFeature = Substitute.For<IStreamIdFeature>();
streamIdFeature.StreamId.Returns(257);

var featureCollection = new FeatureCollection();
featureCollection.Set<IStreamIdFeature>(streamIdFeature);

httpContext.Features.Returns(featureCollection);
// Act
var result = renderer.Render(new LogEventInfo());
// Assert
Assert.Equal("257", result);
}

[Fact]
public void NullTest()
{
// Arrange
var (renderer, httpContext) = CreateWithHttpContext();
httpContext.Features.Returns(new FeatureCollection());
// Act
var result = renderer.Render(new LogEventInfo());
// Assert
Assert.Equal(string.Empty, result);
}

protected override void NullRendersEmptyString()
{
// Arrange
var (renderer, _) = CreateWithHttpContext();

// Act
string result = renderer.Render(LogEventInfo.CreateNullEvent());

// Assert
Assert.Equal("0", result);
}
}
}
#endif