Using new IHtmlEncoders

Fixes: https://github.com/aspnet/Diagnostics/issues/89
This commit is contained in:
Praburaj 2015-03-06 11:29:58 -08:00
parent 00a1127676
commit 18696828cc
12 changed files with 181 additions and 68 deletions

View File

@ -2,6 +2,7 @@
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Http;
using Microsoft.Framework.WebEncoders;
namespace ErrorHandlerSample
{
@ -24,7 +25,7 @@ namespace ErrorHandlerSample
if (error != null)
{
// This error would not normally be exposed to the client
await context.Response.WriteAsync("<br>Error: " + System.Net.WebUtility.HtmlEncode(error.Error.Message) + "<br>\r\n");
await context.Response.WriteAsync("<br>Error: " + HtmlEncoder.Default.HtmlEncode(error.Error.Message) + "<br>\r\n");
}
await context.Response.WriteAsync("<br><a href=\"/\">Home</a><br>\r\n");
await context.Response.WriteAsync("</body></html>\r\n");

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
</body>
</html>

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Http;
using Microsoft.Framework.WebEncoders;
namespace StatusCodePagesSample
{
@ -61,11 +62,11 @@ namespace StatusCodePagesSample
{
var builder = new StringBuilder();
builder.AppendLine("<html><body>");
builder.AppendLine("An error occurred, Status Code: " + WebUtility.HtmlEncode(context.Request.Path.ToString().Substring(1)) + "<br>");
builder.AppendLine("An error occurred, Status Code: " + HtmlEncoder.Default.HtmlEncode(context.Request.Path.ToString().Substring(1)) + "<br>");
var referrer = context.Request.Headers["referer"];
if (!string.IsNullOrEmpty(referrer))
{
builder.AppendLine("<a href=\"" + WebUtility.HtmlEncode(referrer) + "\">Retry " + WebUtility.HtmlEncode(referrer) + "</a><br>");
builder.AppendLine("<a href=\"" + HtmlEncoder.Default.HtmlEncode(referrer) + "\">Retry " + WebUtility.HtmlEncode(referrer) + "</a><br>");
}
builder.AppendLine("</body></html>");
await context.Response.SendAsync(builder.ToString(), "text/html");
@ -78,8 +79,8 @@ namespace StatusCodePagesSample
var builder = new StringBuilder();
builder.AppendLine("<html><body>");
builder.AppendLine("<a href=\"" +
WebUtility.HtmlEncode(context.Request.PathBase.ToString()) + "/missingpage/\">" +
WebUtility.HtmlEncode(context.Request.PathBase.ToString()) + "/missingpage/</a><br>");
HtmlEncoder.Default.HtmlEncode(context.Request.PathBase.ToString()) + "/missingpage/\">" +
HtmlEncoder.Default.HtmlEncode(context.Request.PathBase.ToString()) + "/missingpage/</a><br>");
var space = string.Concat(Enumerable.Repeat("&nbsp;", 12));
builder.AppendFormat("<br><b>{0}{1}{2}</b><br>", "Status Code", space, "Status Code Pages");

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
</body>
</html>

View File

@ -5,9 +5,10 @@
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Diagnostics.Views
{
@ -36,6 +37,11 @@ namespace Microsoft.AspNet.Diagnostics.Views
/// </summary>
protected StreamWriter Output { get; private set; }
/// <summary>
/// Html encoder used to encode content.
/// </summary>
protected IHtmlEncoder HtmlEncoder { get; set; }
/// <summary>
/// Execute an individual request
/// </summary>
@ -46,6 +52,7 @@ namespace Microsoft.AspNet.Diagnostics.Views
Request = Context.Request;
Response = Context.Response;
Output = new StreamWriter(Response.Body);
HtmlEncoder = context.ApplicationServices.GetHtmlEncoder();
await ExecuteAsync();
Output.Dispose();
}
@ -217,7 +224,7 @@ namespace Microsoft.AspNet.Diagnostics.Views
/// <param name="value">The <see cref="string"/> to write.</param>
protected void WriteTo(TextWriter writer, string value)
{
WriteLiteralTo(writer, WebUtility.HtmlEncode(value));
WriteLiteralTo(writer, HtmlEncoder.HtmlEncode(value));
}
/// <summary>
@ -241,5 +248,20 @@ namespace Microsoft.AspNet.Diagnostics.Views
writer.Write(value);
}
}
protected string HtmlEncodeAndReplaceLineBreaks(string input)
{
if (string.IsNullOrEmpty(input))
{
return string.Empty;
}
// Split on line breaks before passing it through the encoder.
// We use the static default encoder since we can't depend on DI in the error handling logic.
return string.Join("<br />" + Environment.NewLine,
input.Split(new[] { "\r\n" }, StringSplitOptions.None)
.SelectMany(s => s.Split(new[] { '\r', '\n' }, StringSplitOptions.None))
.Select(HtmlEncoder.HtmlEncode));
}
}
}
}

View File

@ -95,7 +95,7 @@ using Views
#line hidden
WriteLiteral(": ");
#line 30 "CompilationErrorPage.cshtml"
Output.Write(WebUtility.HtmlEncode(errorDetail.Error.Message).Replace("\r\n", "<br/>").Replace("\r", "<br/>").Replace("\n", "<br/>"));
Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message));
#line default
#line hidden
@ -158,8 +158,8 @@ using Views
#line hidden
WriteLiteral(" <li class=\"frame\"");
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 1370), Tuple.Create("\"", 1390),
Tuple.Create(Tuple.Create("", 1381), Tuple.Create<System.Object, System.Int32>(tabIndex, 1381), false));
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 1308), Tuple.Create("\"", 1328),
Tuple.Create(Tuple.Create("", 1319), Tuple.Create<System.Object, System.Int32>(tabIndex, 1319), false));
WriteLiteral(">\r\n");
#line 45 "CompilationErrorPage.cshtml"
@ -226,8 +226,8 @@ using Views
#line default
#line hidden
WriteLiteral(" in <code");
WriteAttribute("title", Tuple.Create(" title=\"", 1990), Tuple.Create("\"", 2009),
Tuple.Create(Tuple.Create("", 1998), Tuple.Create<System.Object, System.Int32>(frame.File, 1998), false));
WriteAttribute("title", Tuple.Create(" title=\"", 1928), Tuple.Create("\"", 1947),
Tuple.Create(Tuple.Create("", 1936), Tuple.Create<System.Object, System.Int32>(frame.File, 1936), false));
WriteLiteral(">");
#line 58 "CompilationErrorPage.cshtml"
Write(System.IO.Path.GetFileName(frame.File));
@ -242,14 +242,8 @@ using Views
#line default
#line hidden
WriteLiteral(" \r\n");
#line 62 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 62 "CompilationErrorPage.cshtml"
WriteLiteral(" ");
#line 61 "CompilationErrorPage.cshtml"
if (frame.Line != 0 && frame.ContextCode.Any())
{
@ -257,13 +251,13 @@ using Views
#line hidden
WriteLiteral(" <div class=\"source\">\r\n");
#line 65 "CompilationErrorPage.cshtml"
#line 64 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 65 "CompilationErrorPage.cshtml"
#line 64 "CompilationErrorPage.cshtml"
if (frame.PreContextCode != null)
{
@ -271,16 +265,16 @@ using Views
#line hidden
WriteLiteral(" <ol");
WriteAttribute("start", Tuple.Create(" start=\"", 2453), Tuple.Create("\"", 2482),
Tuple.Create(Tuple.Create("", 2461), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 2461), false));
WriteAttribute("start", Tuple.Create(" start=\"", 2353), Tuple.Create("\"", 2382),
Tuple.Create(Tuple.Create("", 2361), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 2361), false));
WriteLiteral(" class=\"collapsible\">\r\n");
#line 68 "CompilationErrorPage.cshtml"
#line 67 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 68 "CompilationErrorPage.cshtml"
#line 67 "CompilationErrorPage.cshtml"
foreach (var line in frame.PreContextCode)
{
@ -288,36 +282,36 @@ using Views
#line hidden
WriteLiteral(" <li><span>");
#line 70 "CompilationErrorPage.cshtml"
#line 69 "CompilationErrorPage.cshtml"
Write(line);
#line default
#line hidden
WriteLiteral("</span></li>\r\n");
#line 71 "CompilationErrorPage.cshtml"
#line 70 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ol>\r\n");
#line 73 "CompilationErrorPage.cshtml"
}
#line 72 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral("\r\n <ol");
WriteAttribute("start", Tuple.Create(" start=\"", 2866), Tuple.Create("\"", 2885),
Tuple.Create(Tuple.Create("", 2874), Tuple.Create<System.Object, System.Int32>(frame.Line, 2874), false));
WriteLiteral(" <ol");
WriteAttribute("start", Tuple.Create(" start=\"", 2763), Tuple.Create("\"", 2782),
Tuple.Create(Tuple.Create("", 2771), Tuple.Create<System.Object, System.Int32>(frame.Line, 2771), false));
WriteLiteral(" class=\"highlight\">\r\n");
#line 76 "CompilationErrorPage.cshtml"
#line 74 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 76 "CompilationErrorPage.cshtml"
#line 74 "CompilationErrorPage.cshtml"
foreach (var line in frame.ContextCode)
{
@ -325,26 +319,26 @@ using Views
#line hidden
WriteLiteral(" <li><span>");
#line 78 "CompilationErrorPage.cshtml"
#line 76 "CompilationErrorPage.cshtml"
Write(line);
#line default
#line hidden
WriteLiteral("</span></li>\r\n");
#line 79 "CompilationErrorPage.cshtml"
#line 77 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ol> \r\n\r\n");
#line 82 "CompilationErrorPage.cshtml"
WriteLiteral(" </ol>\r\n");
#line 79 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 82 "CompilationErrorPage.cshtml"
#line 79 "CompilationErrorPage.cshtml"
if (frame.PostContextCode != null)
{
@ -352,16 +346,16 @@ using Views
#line hidden
WriteLiteral(" <ol");
WriteAttribute("start", Tuple.Create(" start=\'", 3352), Tuple.Create("\'", 3377),
Tuple.Create(Tuple.Create("", 3360), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 3360), false));
WriteAttribute("start", Tuple.Create(" start=\'", 3211), Tuple.Create("\'", 3236),
Tuple.Create(Tuple.Create("", 3219), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 3219), false));
WriteLiteral(" class=\"collapsible\">\r\n");
#line 85 "CompilationErrorPage.cshtml"
#line 82 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 85 "CompilationErrorPage.cshtml"
#line 82 "CompilationErrorPage.cshtml"
foreach (var line in frame.PostContextCode)
{
@ -369,41 +363,41 @@ using Views
#line hidden
WriteLiteral(" <li><span>");
#line 87 "CompilationErrorPage.cshtml"
#line 84 "CompilationErrorPage.cshtml"
Write(line);
#line default
#line hidden
WriteLiteral("</span></li>\r\n");
#line 88 "CompilationErrorPage.cshtml"
#line 85 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ol>\r\n");
#line 90 "CompilationErrorPage.cshtml"
#line 87 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </div>\r\n");
#line 92 "CompilationErrorPage.cshtml"
#line 89 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </li>\r\n");
#line 94 "CompilationErrorPage.cshtml"
#line 91 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ul>\r\n </div>\r\n");
#line 97 "CompilationErrorPage.cshtml"
#line 94 "CompilationErrorPage.cshtml"
}
#line default

View File

@ -27,7 +27,7 @@
<h1>@Resources.ErrorPageHtml_CompilationException</h1>
@if (Model.Options.ShowExceptionDetails)
{
<div class="titleerror">@errorDetail.Error.GetType().Name: @{ Output.Write(WebUtility.HtmlEncode(errorDetail.Error.Message).Replace("\r\n", "<br/>").Replace("\r", "<br/>").Replace("\n", "<br/>")); }</div>
<div class="titleerror">@errorDetail.Error.GetType().Name: @{ Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); }</div>
}
else
{

View File

@ -105,7 +105,7 @@ using Views
#line hidden
WriteLiteral(": ");
#line 37 "ErrorPage.cshtml"
Output.Write(WebUtility.HtmlEncode(errorDetail.Error.Message).Replace("\r\n", "<br/>").Replace("\r", "<br/>").Replace("\n", "<br/>"));
Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message));
#line default
#line hidden
@ -149,8 +149,8 @@ using Views
#line default
#line hidden
WriteLiteral(" in <code");
WriteAttribute("title", Tuple.Create(" title=\"", 2089), Tuple.Create("\"", 2113),
Tuple.Create(Tuple.Create("", 2097), Tuple.Create<System.Object, System.Int32>(firstFrame.File, 2097), false));
WriteAttribute("title", Tuple.Create(" title=\"", 2027), Tuple.Create("\"", 2051),
Tuple.Create(Tuple.Create("", 2035), Tuple.Create<System.Object, System.Int32>(firstFrame.File, 2035), false));
WriteLiteral(">");
#line 52 "ErrorPage.cshtml"
Write(System.IO.Path.GetFileName(firstFrame.File));
@ -398,8 +398,8 @@ using Views
#line hidden
WriteLiteral(" <li class=\"frame\"");
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 4348), Tuple.Create("\"", 4368),
Tuple.Create(Tuple.Create("", 4359), Tuple.Create<System.Object, System.Int32>(tabIndex, 4359), false));
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 4286), Tuple.Create("\"", 4306),
Tuple.Create(Tuple.Create("", 4297), Tuple.Create<System.Object, System.Int32>(tabIndex, 4297), false));
WriteLiteral(">\r\n");
#line 113 "ErrorPage.cshtml"
@ -449,8 +449,8 @@ using Views
#line default
#line hidden
WriteLiteral(" in <code");
WriteAttribute("title", Tuple.Create(" title=\"", 4795), Tuple.Create("\"", 4814),
Tuple.Create(Tuple.Create("", 4803), Tuple.Create<System.Object, System.Int32>(frame.File, 4803), false));
WriteAttribute("title", Tuple.Create(" title=\"", 4733), Tuple.Create("\"", 4752),
Tuple.Create(Tuple.Create("", 4741), Tuple.Create<System.Object, System.Int32>(frame.File, 4741), false));
WriteLiteral(">");
#line 120 "ErrorPage.cshtml"
Write(System.IO.Path.GetFileName(frame.File));
@ -493,8 +493,8 @@ using Views
#line hidden
WriteLiteral(" <ol");
WriteAttribute("start", Tuple.Create(" start=\"", 5275), Tuple.Create("\"", 5304),
Tuple.Create(Tuple.Create("", 5283), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 5283), false));
WriteAttribute("start", Tuple.Create(" start=\"", 5213), Tuple.Create("\"", 5242),
Tuple.Create(Tuple.Create("", 5221), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 5221), false));
WriteLiteral(" class=\"collapsible\">\r\n");
#line 129 "ErrorPage.cshtml"
@ -530,8 +530,8 @@ using Views
#line hidden
WriteLiteral("\r\n <ol");
WriteAttribute("start", Tuple.Create(" start=\"", 5772), Tuple.Create("\"", 5791),
Tuple.Create(Tuple.Create("", 5780), Tuple.Create<System.Object, System.Int32>(frame.Line, 5780), false));
WriteAttribute("start", Tuple.Create(" start=\"", 5710), Tuple.Create("\"", 5729),
Tuple.Create(Tuple.Create("", 5718), Tuple.Create<System.Object, System.Int32>(frame.Line, 5718), false));
WriteLiteral(" class=\"highlight\">\r\n");
#line 137 "ErrorPage.cshtml"
@ -574,8 +574,8 @@ using Views
#line hidden
WriteLiteral(" <ol");
WriteAttribute("start", Tuple.Create(" start=\'", 6318), Tuple.Create("\'", 6343),
Tuple.Create(Tuple.Create("", 6326), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 6326), false));
WriteAttribute("start", Tuple.Create(" start=\'", 6256), Tuple.Create("\'", 6281),
Tuple.Create(Tuple.Create("", 6264), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 6264), false));
WriteLiteral(" class=\"collapsible\">\r\n");
#line 146 "ErrorPage.cshtml"

View File

@ -34,7 +34,7 @@
{
foreach (var errorDetail in Model.ErrorDetails)
{
<div class="titleerror">@errorDetail.Error.GetType().Name: @{ Output.Write(WebUtility.HtmlEncode(errorDetail.Error.Message).Replace("\r\n", "<br/>").Replace("\r", "<br/>").Replace("\n", "<br/>")); }</div>
<div class="titleerror">@errorDetail.Error.GetType().Name: @{ Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); }</div>
@{
StackFrame firstFrame = null;
firstFrame = errorDetail.StackFrames.FirstOrDefault();

View File

@ -4,7 +4,8 @@
"dependencies": {
"Microsoft.AspNet.Diagnostics.Interfaces": "1.0.0-*",
"Microsoft.AspNet.RequestContainer": "1.0.0-*",
"Microsoft.AspNet.WebUtilities": "1.0.0-*"
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
"Microsoft.Framework.WebEncoders": "1.0.0-*"
},
"frameworks": {
"aspnet50": {},

View File

@ -101,6 +101,9 @@ namespace Microsoft.AspNet.Diagnostics.Tests
contextMock
.SetupGet(c => c.Response.Body)
.Returns(responseStream);
contextMock
.SetupGet(c => c.ApplicationServices)
.Returns(() => null);
// Act
await captureMiddleware.Invoke(contextMock.Object);

View File

@ -4,13 +4,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Runtime;
using Microsoft.Framework.WebEncoders;
#if ASPNET50
using Moq;
#endif
@ -121,6 +122,9 @@ namespace Microsoft.AspNet.Diagnostics.Tests
contextMock
.SetupGet(c => c.Response.Body)
.Returns(responseStream);
contextMock
.SetupGet(c => c.ApplicationServices)
.Returns(() => null);
// Act
await middleware.Invoke(contextMock.Object);
@ -136,6 +140,53 @@ namespace Microsoft.AspNet.Diagnostics.Tests
Assert.True(response.Contains("<td>Path2</td>"));
}
}
[Fact]
public async void Invoke_WithMatchingPath_ReturnsInfoPage_UsingCustomHtmlEncoder()
{
// Arrange
var libraryManagerMock = new Mock<ILibraryManager>(MockBehavior.Strict);
libraryManagerMock.Setup(l => l.GetLibraries()).Returns(new ILibraryInformation[] {
new FakeLibraryInformation() { Name ="LibInfo1", Version = "1.0.0-beta1", Path = "Path1" },
});
RequestDelegate next = _ =>
{
return Task.FromResult<object>(null);
};
var middleware = new RuntimeInfoMiddleware(
next,
new RuntimeInfoPageOptions(),
libraryManagerMock.Object);
var buffer = new byte[4096];
using (var responseStream = new MemoryStream(buffer))
{
var contextMock = new Mock<HttpContext>(MockBehavior.Strict);
contextMock
.SetupGet(c => c.Request.Path)
.Returns(new PathString("/runtimeinfo"));
contextMock
.SetupGet(c => c.Response.Body)
.Returns(responseStream);
contextMock
.SetupGet(c => c.ApplicationServices)
.Returns(new ServiceCollection().
AddInstance<IHtmlEncoder>(new CustomHtmlEncoder()).
BuildServiceProvider());
// Act
await middleware.Invoke(contextMock.Object);
// Assert
string response = Encoding.UTF8.GetString(buffer);
Assert.True(response.Contains("<td>[LibInfo1]</td>"));
Assert.True(response.Contains("<td>[1.0.0-beta1]</td>"));
Assert.True(response.Contains("<td>[Path1]</td>"));
}
}
#endif
private class FakeLibraryInformation : ILibraryInformation
@ -170,5 +221,23 @@ namespace Microsoft.AspNet.Diagnostics.Tests
}
}
}
private class CustomHtmlEncoder : IHtmlEncoder
{
public string HtmlEncode(string value)
{
return "[" + value + "]";
}
public void HtmlEncode(string value, int startIndex, int charCount, TextWriter output)
{
throw new NotImplementedException();
}
public void HtmlEncode(char[] value, int startIndex, int charCount, TextWriter output)
{
throw new NotImplementedException();
}
}
}
}