将 asp.net 核心 2.0 网址重定向为小写
Redirect asp.net core 2.0 urls to lowercase
我看到您可以在 ASP.NET Core 2.0 中配置路由以生成小写 urls,如下所述:
使用这个:
services.AddRouting(options => options.LowercaseUrls = true);
然而,尽管生成 urls 很好,但它似乎没有做任何实际执行它们的事情,也就是说,重定向任何不全是小写的 urls到相应的小写 url(最好通过 301 重定向)。
我知道人们通过不同大小写的 url 访问我的网站,我希望他们都永久小写。
通过 RewriteOptions 和 Regex 进行标准重定向是唯一的方法吗?执行此操作的适当表达式是什么:
var options = new RewriteOptions().AddRedirect("???", "????");
或者有别的方法吗?
我很感激这已经有好几个月了,但是对于可能正在寻找相同解决方案的人,您可以添加一个复杂的重定向实现 IRule
例如:
public class RedirectLowerCaseRule : IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public void ApplyRule(RewriteContext context)
{
HttpRequest request = context.HttpContext.Request;
PathString path = context.HttpContext.Request.Path;
HostString host = context.HttpContext.Request.Host;
if (path.HasValue && path.Value.Any(char.IsUpper) || host.HasValue && host.Value.Any(char.IsUpper))
{
HttpResponse response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = (request.Scheme + "://" + host.Value + request.PathBase + request.Path).ToLower() + request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
}
然后可以在 Configure
方法下将其应用到您的 Startup.cs
中:
new RewriteOptions().Add(new RedirectLowerCaseRule());
希望对您有所帮助!
您确定要重定向吗?如果没有,并且您的目标是在您的主机和路径中没有大写这样的东西,您可以使用以下 IRule。这让我确信,无论我在管道中查看什么路径,它都是小写的。
public class RewriteLowerCaseRule : IRule
{
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var host = request.Host;
var pathBase = request.PathBase;
var path = request.Path;
if (host.HasValue)
{
if (host.Port == null)
{
request.Host = new HostString(host.Host.ToLower());
}
else
{
request.Host = new HostString(host.Host.ToLower(), (int) host.Port);
}
}
if (pathBase.HasValue)
{
request.PathBase = new PathString(pathBase.Value.ToLower());
}
if (path.HasValue)
{
request.Path = new PathString(path.Value.ToLower());
request.PathBase = new PathString(pathBase.Value.ToLower());
}
context.Result = RuleResult.ContinueRules;
}
}
用法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseRewriter(new RewriteOptions().Add(new RewriteLowerCaseRule()));
...
}
添加为答案,因为我(还)不能发表评论。这是对 Ben Maxfields 回答的补充。
使用他的代码 http://www.example.org/Example/example
不会被重定向,因为 PathBase
没有检查大写字母(即使它用于构建新的小写 URI)。
所以根据他的代码,我最终使用了这个:
public class RedirectLowerCaseRule : IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public void ApplyRule(RewriteContext context)
{
HttpRequest request = context.HttpContext.Request;
PathString path = context.HttpContext.Request.Path;
PathString pathbase = context.HttpContext.Request.PathBase;
HostString host = context.HttpContext.Request.Host;
if ((path.HasValue && path.Value.Any(char.IsUpper)) || (host.HasValue && host.Value.Any(char.IsUpper)) || (pathbase.HasValue && pathbase.Value.Any(char.IsUpper)))
{
Console.WriteLine("Redirect should happen");
HttpResponse response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = (request.Scheme + "://" + host.Value + request.PathBase + request.Path).ToLower() + request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
}
实施方式略有不同,同样受到 this other thread 的启发。
public class RedirectLowerCaseRule : IRule
{
public void ApplyRule(RewriteContext context)
{
HttpRequest request = context.HttpContext.Request;
string url = request.Scheme + "://" + request.Host + request.PathBase + request.Path;
bool isGet = request.Method.ToLowerInvariant().Contains("get");
if ( isGet && url.Contains(".") == false && Regex.IsMatch(url, @"[A-Z]") )
{
HttpResponse response = context.HttpContext.Response;
response.Clear();
response.StatusCode = StatusCodes.Status301MovedPermanently;
response.Headers[HeaderNames.Location] = url.ToLowerInvariant() + request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
}
我认为有用的更改:
使用 ToLowerInvariant()
而不是 ToLower()
(查看可能的问题 here)
保留端口号。
绕过 GET 以外的请求方法。
用点绕过请求,假设像 js/css/images 等静态文件应该保留任何大写字母。
使用 Microsoft.AspNetCore.Http.StatusCodes
.
我的两分钱...基于https://github.com/aspnet/AspNetCore/blob/master/src/Middleware/Rewrite/src/RedirectToWwwRule.cs
public class RedirectToLowercaseRule : IRule
{
private readonly int _statusCode;
public RedirectToLowercaseRule(int statusCode)
{
_statusCode = statusCode;
}
public void ApplyRule(RewriteContext context)
{
var req = context.HttpContext.Request;
if (!req.Scheme.Any(char.IsUpper)
&& !req.Host.Value.Any(char.IsUpper)
&& !req.PathBase.Value.Any(char.IsUpper)
&& !req.Path.Value.Any(char.IsUpper))
{
context.Result = RuleResult.ContinueRules;
return;
}
var newUrl = UriHelper.BuildAbsolute(req.Scheme.ToLowerInvariant(), new HostString(req.Host.Value.ToLowerInvariant()), req.PathBase.Value.ToLowerInvariant(), req.Path.Value.ToLowerInvariant(), req.QueryString);
var response = context.HttpContext.Response;
response.StatusCode = _statusCode;
response.Headers[HeaderNames.Location] = newUrl;
context.Result = RuleResult.EndResponse;
context.Logger.RedirectedToLowercase();
}
}
使用扩展方法:
public static class RewriteOptionsExtensions
{
public static RewriteOptions AddRedirectToLowercase(this RewriteOptions options, int statusCode)
{
options.Add(new RedirectToLowercaseRule(statusCode));
return options;
}
public static RewriteOptions AddRedirectToLowercase(this RewriteOptions options)
{
return AddRedirectToLowercase(options, StatusCodes.Status307TemporaryRedirect);
}
public static RewriteOptions AddRedirectToLowercasePermanent(this RewriteOptions options)
{
return AddRedirectToLowercase(options, StatusCodes.Status308PermanentRedirect);
}
}
和日志记录:
internal static class MiddlewareLoggingExtensions
{
private static readonly Action<ILogger, Exception> _redirectedToLowercase = LoggerMessage.Define(LogLevel.Information, new EventId(1, "RedirectedToLowercase"), "Request redirected to lowercase");
public static void RedirectedToLowercase(this ILogger logger)
{
_redirectedToLowercase(logger, null);
}
}
和用法:
app.UseRewriter(new RewriteOptions()
.AddRedirectToLowercase());
其他考虑因素是状态代码的选择。我在扩展方法中使用了 307 和 308,因为它们可以防止在请求期间更改请求方法(例如,从 GET 到 POST),但是如果你想允许这种行为,你可以使用 301 和 302。请参阅 了解更多信息。
我看到您可以在 ASP.NET Core 2.0 中配置路由以生成小写 urls,如下所述:
使用这个:
services.AddRouting(options => options.LowercaseUrls = true);
然而,尽管生成 urls 很好,但它似乎没有做任何实际执行它们的事情,也就是说,重定向任何不全是小写的 urls到相应的小写 url(最好通过 301 重定向)。
我知道人们通过不同大小写的 url 访问我的网站,我希望他们都永久小写。
通过 RewriteOptions 和 Regex 进行标准重定向是唯一的方法吗?执行此操作的适当表达式是什么:
var options = new RewriteOptions().AddRedirect("???", "????");
或者有别的方法吗?
我很感激这已经有好几个月了,但是对于可能正在寻找相同解决方案的人,您可以添加一个复杂的重定向实现 IRule
例如:
public class RedirectLowerCaseRule : IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public void ApplyRule(RewriteContext context)
{
HttpRequest request = context.HttpContext.Request;
PathString path = context.HttpContext.Request.Path;
HostString host = context.HttpContext.Request.Host;
if (path.HasValue && path.Value.Any(char.IsUpper) || host.HasValue && host.Value.Any(char.IsUpper))
{
HttpResponse response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = (request.Scheme + "://" + host.Value + request.PathBase + request.Path).ToLower() + request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
}
然后可以在 Configure
方法下将其应用到您的 Startup.cs
中:
new RewriteOptions().Add(new RedirectLowerCaseRule());
希望对您有所帮助!
您确定要重定向吗?如果没有,并且您的目标是在您的主机和路径中没有大写这样的东西,您可以使用以下 IRule。这让我确信,无论我在管道中查看什么路径,它都是小写的。
public class RewriteLowerCaseRule : IRule
{
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var host = request.Host;
var pathBase = request.PathBase;
var path = request.Path;
if (host.HasValue)
{
if (host.Port == null)
{
request.Host = new HostString(host.Host.ToLower());
}
else
{
request.Host = new HostString(host.Host.ToLower(), (int) host.Port);
}
}
if (pathBase.HasValue)
{
request.PathBase = new PathString(pathBase.Value.ToLower());
}
if (path.HasValue)
{
request.Path = new PathString(path.Value.ToLower());
request.PathBase = new PathString(pathBase.Value.ToLower());
}
context.Result = RuleResult.ContinueRules;
}
}
用法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseRewriter(new RewriteOptions().Add(new RewriteLowerCaseRule()));
...
}
添加为答案,因为我(还)不能发表评论。这是对 Ben Maxfields 回答的补充。
使用他的代码 http://www.example.org/Example/example
不会被重定向,因为 PathBase
没有检查大写字母(即使它用于构建新的小写 URI)。
所以根据他的代码,我最终使用了这个:
public class RedirectLowerCaseRule : IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public void ApplyRule(RewriteContext context)
{
HttpRequest request = context.HttpContext.Request;
PathString path = context.HttpContext.Request.Path;
PathString pathbase = context.HttpContext.Request.PathBase;
HostString host = context.HttpContext.Request.Host;
if ((path.HasValue && path.Value.Any(char.IsUpper)) || (host.HasValue && host.Value.Any(char.IsUpper)) || (pathbase.HasValue && pathbase.Value.Any(char.IsUpper)))
{
Console.WriteLine("Redirect should happen");
HttpResponse response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = (request.Scheme + "://" + host.Value + request.PathBase + request.Path).ToLower() + request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
}
实施方式略有不同,同样受到 this other thread 的启发。
public class RedirectLowerCaseRule : IRule
{
public void ApplyRule(RewriteContext context)
{
HttpRequest request = context.HttpContext.Request;
string url = request.Scheme + "://" + request.Host + request.PathBase + request.Path;
bool isGet = request.Method.ToLowerInvariant().Contains("get");
if ( isGet && url.Contains(".") == false && Regex.IsMatch(url, @"[A-Z]") )
{
HttpResponse response = context.HttpContext.Response;
response.Clear();
response.StatusCode = StatusCodes.Status301MovedPermanently;
response.Headers[HeaderNames.Location] = url.ToLowerInvariant() + request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
}
我认为有用的更改:
使用 ToLowerInvariant()
而不是 ToLower()
(查看可能的问题 here)
保留端口号。
绕过 GET 以外的请求方法。
用点绕过请求,假设像 js/css/images 等静态文件应该保留任何大写字母。
使用 Microsoft.AspNetCore.Http.StatusCodes
.
我的两分钱...基于https://github.com/aspnet/AspNetCore/blob/master/src/Middleware/Rewrite/src/RedirectToWwwRule.cs
public class RedirectToLowercaseRule : IRule
{
private readonly int _statusCode;
public RedirectToLowercaseRule(int statusCode)
{
_statusCode = statusCode;
}
public void ApplyRule(RewriteContext context)
{
var req = context.HttpContext.Request;
if (!req.Scheme.Any(char.IsUpper)
&& !req.Host.Value.Any(char.IsUpper)
&& !req.PathBase.Value.Any(char.IsUpper)
&& !req.Path.Value.Any(char.IsUpper))
{
context.Result = RuleResult.ContinueRules;
return;
}
var newUrl = UriHelper.BuildAbsolute(req.Scheme.ToLowerInvariant(), new HostString(req.Host.Value.ToLowerInvariant()), req.PathBase.Value.ToLowerInvariant(), req.Path.Value.ToLowerInvariant(), req.QueryString);
var response = context.HttpContext.Response;
response.StatusCode = _statusCode;
response.Headers[HeaderNames.Location] = newUrl;
context.Result = RuleResult.EndResponse;
context.Logger.RedirectedToLowercase();
}
}
使用扩展方法:
public static class RewriteOptionsExtensions
{
public static RewriteOptions AddRedirectToLowercase(this RewriteOptions options, int statusCode)
{
options.Add(new RedirectToLowercaseRule(statusCode));
return options;
}
public static RewriteOptions AddRedirectToLowercase(this RewriteOptions options)
{
return AddRedirectToLowercase(options, StatusCodes.Status307TemporaryRedirect);
}
public static RewriteOptions AddRedirectToLowercasePermanent(this RewriteOptions options)
{
return AddRedirectToLowercase(options, StatusCodes.Status308PermanentRedirect);
}
}
和日志记录:
internal static class MiddlewareLoggingExtensions
{
private static readonly Action<ILogger, Exception> _redirectedToLowercase = LoggerMessage.Define(LogLevel.Information, new EventId(1, "RedirectedToLowercase"), "Request redirected to lowercase");
public static void RedirectedToLowercase(this ILogger logger)
{
_redirectedToLowercase(logger, null);
}
}
和用法:
app.UseRewriter(new RewriteOptions()
.AddRedirectToLowercase());
其他考虑因素是状态代码的选择。我在扩展方法中使用了 307 和 308,因为它们可以防止在请求期间更改请求方法(例如,从 GET 到 POST),但是如果你想允许这种行为,你可以使用 301 和 302。请参阅