Adding RedirectToWwwRule and extension (#297)

This commit is contained in:
Colin Farr 2018-02-09 22:13:43 +00:00 committed by Justin Kotalik
parent 840756bdde
commit 103190796f
4 changed files with 171 additions and 0 deletions

View File

@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite.Logging
private static readonly Action<ILogger, Exception> _modRewriteDidNotMatchRule;
private static readonly Action<ILogger, Exception> _modRewriteMatchedRule;
private static readonly Action<ILogger, Exception> _redirectedToHttps;
private static readonly Action<ILogger, Exception> _redirectedToWww;
private static readonly Action<ILogger, string, Exception> _redirectSummary;
private static readonly Action<ILogger, string, Exception> _rewriteSummary;
private static readonly Action<ILogger, string, Exception> _abortedRequest;
@ -82,6 +83,11 @@ namespace Microsoft.AspNetCore.Rewrite.Logging
LogLevel.Debug,
12,
"Request to {requestedUrl} was ended");
_redirectedToWww = LoggerMessage.Define(
LogLevel.Information,
13,
"Request redirected to www");
}
public static void RewriteMiddlewareRequestContinueResults(this ILogger logger, string currentUrl)
@ -124,6 +130,11 @@ namespace Microsoft.AspNetCore.Rewrite.Logging
_redirectedToHttps(logger, null);
}
public static void RedirectedToWww(this ILogger logger)
{
_redirectedToWww(logger, null);
}
public static void RedirectedSummary(this ILogger logger, string redirectedUrl)
{
_redirectSummary(logger, redirectedUrl, null);

View File

@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Rewrite.Logging;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Rewrite.Internal
{
public class RedirectToWwwRule : IRule
{
public readonly int _statusCode;
public RedirectToWwwRule(int statusCode)
{
_statusCode = statusCode;
}
public virtual void ApplyRule(RewriteContext context)
{
var req = context.HttpContext.Request;
if (req.Host.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
var wwwHost = new HostString($"www.{req.Host.Value}");
var newUrl = UriHelper.BuildAbsolute(req.Scheme, wwwHost, req.PathBase, req.Path, req.QueryString);
var response = context.HttpContext.Response;
response.StatusCode = _statusCode;
response.Headers[HeaderNames.Location] = newUrl;
context.Result = RuleResult.EndResponse;
context.Logger?.RedirectedToWww();
}
}
}

View File

@ -117,5 +117,35 @@ namespace Microsoft.AspNetCore.Rewrite
options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
return options;
}
/// <summary>
/// Permanently redirects the request to the www subdomain if the request is non-www.
/// </summary>
/// <param name="options">The <see cref="RewriteOptions"/>.</param>
/// <returns></returns>
public static RewriteOptions AddRedirectToWwwPermanent(this RewriteOptions options)
{
return AddRedirectToWww(options, statusCode: StatusCodes.Status308PermanentRedirect);
}
/// <summary>
/// Redirect the request to the www subdomain if the incoming request is non-www.
/// </summary>
/// <param name="options">The <see cref="RewriteOptions"/>.</param>
public static RewriteOptions AddRedirectToWww(this RewriteOptions options)
{
return AddRedirectToWww(options, statusCode: StatusCodes.Status307TemporaryRedirect);
}
/// <summary>
/// Redirect the request to the www subdomain if the incoming request is non-www.
/// </summary>
/// <param name="options">The <see cref="RewriteOptions"/>.</param>
/// <param name="statusCode">The status code to add to the response.</param>
public static RewriteOptions AddRedirectToWww(this RewriteOptions options, int statusCode)
{
options.Rules.Add(new RedirectToWwwRule(statusCode));
return options;
}
}
}

View File

@ -147,6 +147,91 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
Assert.Equal(StatusCodes.Status301MovedPermanently, (int)response.StatusCode);
}
[Theory]
[InlineData(StatusCodes.Status301MovedPermanently)]
[InlineData(StatusCodes.Status302Found)]
[InlineData(StatusCodes.Status307TemporaryRedirect)]
[InlineData(StatusCodes.Status308PermanentRedirect)]
public async Task CheckRedirectToWwwWithStatusCode(int statusCode)
{
var options = new RewriteOptions().AddRedirectToWww(statusCode: statusCode);
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseRewriter(options);
});
var server = new TestServer(builder);
var response = await server.CreateClient().GetAsync(new Uri("https://example.com"));
Assert.Equal("https://www.example.com/", response.Headers.Location.OriginalString);
Assert.Equal(statusCode, (int)response.StatusCode);
}
[Theory]
[InlineData("http://example.com", "http://www.example.com/")]
[InlineData("https://example.com", "https://www.example.com/")]
[InlineData("http://example.com:8081", "http://www.example.com:8081/")]
[InlineData("http://example.com:8081/example?q=1", "http://www.example.com:8081/example?q=1")]
public async Task CheckRedirectToWww(string requestUri, string redirectUri)
{
var options = new RewriteOptions().AddRedirectToWww();
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseRewriter(options);
});
var server = new TestServer(builder);
var response = await server.CreateClient().GetAsync(new Uri(requestUri));
Assert.Equal(redirectUri, response.Headers.Location.OriginalString);
Assert.Equal(StatusCodes.Status307TemporaryRedirect, (int)response.StatusCode);
}
[Fact]
public async Task CheckPermanentRedirectToWww()
{
var options = new RewriteOptions().AddRedirectToWwwPermanent();
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseRewriter(options);
});
var server = new TestServer(builder);
var response = await server.CreateClient().GetAsync(new Uri("https://example.com"));
Assert.Equal("https://www.example.com/", response.Headers.Location.OriginalString);
Assert.Equal(StatusCodes.Status308PermanentRedirect, (int)response.StatusCode);
}
[Theory]
[InlineData("http://www.example.com")]
[InlineData("https://www.example.com")]
[InlineData("http://www.example.com:8081")]
[InlineData("https://www.example.com:8081")]
[InlineData("https://www.example.com:8081/example?q=1")]
[InlineData("http://localhost")]
[InlineData("https://localhost")]
[InlineData("http://localhost:8081")]
[InlineData("https://localhost:8081")]
[InlineData("https://localhost:8081/example?q=1")]
public async Task CheckNoRedirectToWww(string requestUri)
{
var options = new RewriteOptions().AddRedirectToWww();
var builder = new WebHostBuilder()
.Configure(app =>
{
app.UseRewriter(options);
});
var server = new TestServer(builder);
var response = await server.CreateClient().GetAsync(new Uri(requestUri));
Assert.Null(response.Headers.Location);
}
[Fact]
public async Task CheckIfEmptyStringRedirectCorrectly()
{