将asp.net core 2.0 url重定向到小写

问题描述 投票:8回答:4

我已经看到你可以在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("???", "????");

还是有另一种方式?

url-redirection asp.net-core-2.0 lowercase
4个回答
5
投票

我很欣赏这已经有好几个月了,但是对于那些可能正在寻找相同解决方案的人来说,你可以添加一个复杂的重定向来实现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());

希望这可以帮助!


0
投票

添加为答案,因为我无法评论(还)。这是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;
        }
    }
}

0
投票

略有不同的实施,也受到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


-2
投票

您确定要重定向吗?如果没有,并且您的目标是在主机和路径中没有大写字母,则可以使用以下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()));
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.