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 ${aspnet-request-headers} for rendering headers #473

Merged
merged 3 commits into from
Sep 20, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
115 changes: 115 additions & 0 deletions src/Shared/LayoutRenderers/AspNetRequestHeadersLayoutRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System.Collections.Generic;
using System.Text;
using NLog.Config;
using NLog.LayoutRenderers;
using NLog.Web.Internal;
using System;
#if !ASP_NET_CORE
using System.Collections.Specialized;
using System.Linq;
#else
using Microsoft.AspNetCore.Http;
#endif

namespace NLog.Web.LayoutRenderers
{
/// <summary>
/// ASP.NET Request Headers
/// </summary>
/// <para>Example usage of ${aspnet-request-headers}</para>
/// <example>
/// <code lang="NLog Layout Renderer">
/// ${aspnet-request-headers:OutputFormat=Flat}
/// ${aspnet-request-headers:OutputFormat=Json}
/// ${aspnet-request-headers:OutputFormat=Json:HeaderNames=username}
/// ${aspnet-request-headers:OutputFormat=Json:Exclude=access_token}
/// </code>
/// </example>
[LayoutRenderer("aspnet-request-headers")]
[ThreadSafe]
public class AspNetRequestHeadersLayoutRenderer : AspNetLayoutMultiValueRendererBase
{
/// <summary>
/// Header names to be rendered.
/// If <c>null</c> or empty array, all headers will be rendered.
/// </summary>
public List<string> HeaderNames { get; set; }

/// <summary>
/// Gets or sets the keys to exclude from the output. If omitted, none are excluded.
/// </summary>
/// <docgen category='Rendering Options' order='10' />
#if ASP_NET_CORE
public ISet<string> Exclude { get; set; }
#else
public HashSet<string> Exclude { get; set; }
#endif

/// <summary>
/// Initializes a new instance of the <see cref="AspNetRequestHeadersLayoutRenderer" /> class.
/// </summary>
public AspNetRequestHeadersLayoutRenderer()
{
Exclude = new HashSet<string>(new[] { "ALL_HTTP", "ALL_RAW", "AUTH_PASSWORD" }, StringComparer.OrdinalIgnoreCase);
}

/// <summary>
/// Renders the ASP.NET Headers appends it to the specified <see cref="StringBuilder" />.
/// </summary>
/// <param name="builder">The <see cref="StringBuilder" /> to append the rendered data to.</param>
/// <param name="logEvent">Logging event.</param>
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
{
var httpRequest = HttpContextAccessor.HttpContext.TryGetRequest();
if (httpRequest == null)
{
return;
}

var headers = httpRequest.Headers;
if (headers?.Count > 0)
{
bool excludeKeys = (HeaderNames == null || HeaderNames.Count == 0) && Exclude?.Count > 0;
ThomasArdal marked this conversation as resolved.
Show resolved Hide resolved
var headerValues = GetHeaderValues(headers, excludeKeys);
SerializePairs(headerValues, builder, logEvent);
}
}

#if !ASP_NET_CORE
private IEnumerable<KeyValuePair<string, string>> GetHeaderValues(NameValueCollection headers, bool excludeKeys)
{
var headerNames = HeaderNames?.Count > 0 ? HeaderNames : headers.Keys.Cast<string>().ToList();
foreach (var headerName in headerNames)
{
if (excludeKeys && Exclude.Contains(headerName))
continue;

var headerValue = headers[headerName];
if (headerValue == null)
{
continue;
}

yield return new KeyValuePair<string, string>(headerName, headerValue);
}
}
#else
private IEnumerable<KeyValuePair<string, string>> GetHeaderValues(IHeaderDictionary headers, bool excludeKeys)
{
var headerNames = HeaderNames?.Count > 0 ? HeaderNames : headers.Keys;
foreach (var headerName in headerNames)
{
if (excludeKeys && Exclude.Contains(headerName))
continue;

if (!headers.TryGetValue(headerName, out var headerValue))
{
continue;
}

yield return new KeyValuePair<string, string>(headerName, headerValue);
}
}
#endif
}
}
Loading