diff --git a/src/Shared/LayoutRenderers/AspNetRequestUrlRenderer.cs b/src/Shared/LayoutRenderers/AspNetRequestUrlRenderer.cs
index 3ba59e115..ed0de8596 100644
--- a/src/Shared/LayoutRenderers/AspNetRequestUrlRenderer.cs
+++ b/src/Shared/LayoutRenderers/AspNetRequestUrlRenderer.cs
@@ -5,6 +5,7 @@
using NLog.Web.Internal;
#if ASP_NET_CORE
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
#else
using System.Collections.Specialized;
@@ -24,7 +25,7 @@ namespace NLog.Web.LayoutRenderers
/// ${aspnet-request-url:IncludePort=true} - produces http://www.exmaple.com:80/
/// ${aspnet-request-url:IncludePort=false} - produces http://www.exmaple.com/
/// ${aspnet-request-url:IncludeScheme=false} - produces www.exmaple.com/
- /// ${aspnet-request-url:IncludePort=true:IncludeQueryString=true} - produces http://www.exmaple.com:80/?t=1
+ /// ${aspnet-request-url:IncludePort=true:IncludeQueryString=true} - produces http://www.exmaple.com:80/?t=1
///
///
[LayoutRenderer("aspnet-request-url")]
@@ -37,7 +38,7 @@ public class AspNetRequestUrlRenderer : AspNetLayoutRendererBase
public bool IncludeQueryString { get; set; } = false;
///
- /// To specify whether to include /exclude the Port. Default is false.
+ /// To specify whether to include / exclude the Port. Default is false.
///
public bool IncludePort { get; set; } = false;
@@ -51,6 +52,11 @@ public class AspNetRequestUrlRenderer : AspNetLayoutRendererBase
///
public bool IncludeScheme { get; set; } = true;
+ ///
+ /// To specify whether to use raw path and full query (for ASP.NET Core only). Default is false.
+ ///
+ public bool UseRawTarget { get; set; } = false;
+
///
/// Renders the Request URL from the HttpRequest
///
@@ -112,11 +118,20 @@ private void RenderUrl(HttpRequest httpRequest, StringBuilder builder)
builder.Append(httpRequest.Host.Port.Value);
}
- builder.Append(httpRequest.PathBase.ToUriComponent());
- builder.Append(httpRequest.Path.ToUriComponent());
- if (IncludeQueryString)
+ IHttpRequestFeature httpRequestFeature;
+ if (UseRawTarget && (httpRequestFeature = httpRequest.HttpContext.Features.Get()) != null)
{
- builder.Append(httpRequest.QueryString.Value);
+ builder.Append(httpRequestFeature.RawTarget);
+ }
+ else
+ {
+ builder.Append(httpRequest.PathBase.ToUriComponent());
+ builder.Append(httpRequest.Path.ToUriComponent());
+
+ if (IncludeQueryString)
+ {
+ builder.Append(httpRequest.QueryString.Value);
+ }
}
}
#endif
diff --git a/tests/Shared/LayoutRenderers/AspNetRequestUrlRendererTests.cs b/tests/Shared/LayoutRenderers/AspNetRequestUrlRendererTests.cs
index 6752d8290..96f703581 100644
--- a/tests/Shared/LayoutRenderers/AspNetRequestUrlRendererTests.cs
+++ b/tests/Shared/LayoutRenderers/AspNetRequestUrlRendererTests.cs
@@ -10,6 +10,7 @@
using Microsoft.Extensions.Primitives;
using HttpContextBase = Microsoft.AspNetCore.Http.HttpContext;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
#endif
using NLog.Web.LayoutRenderers;
using NSubstitute;
@@ -147,7 +148,30 @@ public void UrlPresentRenderNonEmpty_ExcludeHost_IncludeQueryString()
Assert.Equal("http:///Test.asp?t=1", result);
}
- private static AspNetRequestUrlRenderer CreateRenderer(string hostBase, string queryString = "", string scheme = "http", string page = "/", string pathBase = "")
+ [Fact]
+ public void UrlPresentRenderNonEmpty_UseRawTarget()
+ {
+ var renderer = CreateRenderer("www.google.com:80", "?t=1", "http", "/Test.asp", rawTarget: "raw");
+ renderer.UseRawTarget = true;
+
+ string result = renderer.Render(LogEventInfo.CreateNullEvent());
+
+ Assert.Equal("http://raw", result);
+ }
+
+ [Fact]
+ public void UrlPresentRenderNonEmpty_UseRawTarget_IncludeQueryString()
+ {
+ var renderer = CreateRenderer("www.google.com:80", "?t=1", "http", "/Test.asp", rawTarget: "raw");
+ renderer.UseRawTarget = true;
+ renderer.IncludeQueryString = true;
+
+ string result = renderer.Render(LogEventInfo.CreateNullEvent());
+
+ Assert.Equal("http://raw", result);
+ }
+
+ private static AspNetRequestUrlRenderer CreateRenderer(string hostBase, string queryString = "", string scheme = "http", string page = "/", string pathBase = "", string rawTarget = null)
{
var (renderer, httpContext) = CreateWithHttpContext();
@@ -160,8 +184,36 @@ private static AspNetRequestUrlRenderer CreateRenderer(string hostBase, string q
httpContext.Request.QueryString.Returns(new QueryString(queryString));
httpContext.Request.Host.Returns(new HostString(hostBase));
httpContext.Request.Scheme.Returns(scheme);
+
+ if (rawTarget != null)
+ {
+ var httpRequestFeature = new HttpRequestFeatureMock();
+ httpRequestFeature.RawTarget = rawTarget;
+ httpContext.Features.Get().Returns(httpRequestFeature);
+ }
#endif
return renderer;
}
+
+#if ASP_NET_CORE
+
+ private class HttpRequestFeatureMock : IHttpRequestFeature
+ {
+ #region Implementation of IHttpRequestFeature
+
+ public Stream Body { get; set; }
+ public IHeaderDictionary Headers { get; set; }
+ public string Method { get; set; }
+ public string Path { get; set; }
+ public string PathBase { get; set; }
+ public string Protocol { get; set; }
+ public string QueryString { get; set; }
+ public string RawTarget { get; set; }
+ public string Scheme { get; set; }
+
+ #endregion Implementation of IHttpRequestFeature
+ }
+
+#endif
}
}