我已经看到你可以在ASP.NET Core 2.0中配置路由以生成小写网址,如下所述:https://stackoverflow.com/a/45777372/83825
使用这个:
services.AddRouting(options => options.LowercaseUrls = true);
但是,虽然这对于生成URL很好,但它似乎没有做任何实际的ENFORCE,也就是说,将任何非小写的url重定向到相应的小写url(最好是通过301重定向)。
我知道人们通过不同的套管网址访问我的网站,我希望它们永久都是小写的。
通过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;
}
}
}
然后可以在Startup.cs
方法下应用于Configure
:
new RewriteOptions().Add(new RedirectLowerCaseRule());
希望这可以帮助!
添加为答案,因为我无法评论(还)。这是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
。
您确定要重定向吗?如果没有,并且您的目标是在主机和路径中没有大写字母,则可以使用以下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()));
...
}