使用Asp.Net核心中间件将非WWW重定向到WWW

时间:2017-05-06 17:29:37

标签: regex asp.net-core url-rewriting asp.net-core-middleware

在ASP.Net Core应用程序启动中,我有:

RewriteOptions rewriteOptions = new RewriteOptions(); 

rewriteOptions.AddRedirectToHttps();

applicationBuilder.UseRewriter(rewriteOptions);

在制作时我需要将所有非WWW重定向到WWW Urls

例如:

domain.com/about > www.domain.com/about

如何使用重写中间件执行此操作?

我认为这可以使用AddRedirect和Regex完成:

Github - ASP.NET Core Redirect Docs

但不确定该怎么做......

8 个答案:

答案 0 :(得分:13)

可重用的替代方法是创建自定义重写规则和相应的扩展方法,以将规则添加到重写选项。这与AddRedirectToHttps的工作方式非常相似。

自定义规则:

public class RedirectToWwwRule : IRule
{
    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 = 301;
        response.Headers[HeaderNames.Location] = newUrl;
        context.Result = RuleResult.EndResponse;
    }
}

扩展方法:

public static class RewriteOptionsExtensions
{
    public static RewriteOptions AddRedirectToWww(this RewriteOptions options)
    {
        options.Rules.Add(new RedirectToWwwRule());
        return options;
    }
}

用法:

var options = new RewriteOptions();
options.AddRedirectToWww();
options.AddRedirectToHttps();
app.UseRewriter(options);

重写中间件的未来版本将包含规则和相应的扩展方法。见this pull request

答案 1 :(得分:3)

我更多的是Apache用户,幸运的是,ASP.NET Core中的URL重写中间件提供了一种名为AddApacheModRewrite的方法,可以动态执行mod_rewrite规则。

1-创建一个.txt文件,无论名称如何,并将这两行放入其中:

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

2-然后以这种方式调用它:

AddApacheModRewrite(env.ContentRootFileProvider, "Rules.txt")

完成!

答案 2 :(得分:3)

只使用正则表达式

查找^(https?://)?((?!www\.)(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))

替换$1www.$2

扩展

 ^                             # BOS
 (                             # (1 start), optional http(s)
      https?  ://
 )?                            # (1 end)
 (                             # (2 start), domains without www prefix
      (?! www\. )
      (?:
           (?: [a-z\u00a1-\uffff0-9]+ -? )*
           [a-z\u00a1-\uffff0-9]+ 
      )
      (?:
           \.
           (?: [a-z\u00a1-\uffff0-9]+ -? )*
           [a-z\u00a1-\uffff0-9]+ 
      )*
      (?:
           \.
           (?: [a-z\u00a1-\uffff]{2,} )
      )
 )                             # (2 end)

答案 3 :(得分:2)

目前还不清楚AddRedirect方法是做什么以及它是否实际接受正则表达式。

但要插入" www"没有" www"?的网址 您可以尝试使用这些字符串:

string pattern = @"^(https?://)(?!www[.])(.*)$";
string replacement = "$1www.$2";

//Regex rgx = new Regex(pattern);
//string redirectUrl = rgx.Replace(url, replacement);

由于协议之后的前瞻性前瞻(?!www[.]),它会忽略http://www.what.ever等字符串

$ 1和$ 2是第一和第二个捕获组。

答案 4 :(得分:1)

我认为除非使用正则表达式,否则您可以使用Uri类来重建您的网址

var uri = new Uri("http://example.com/test/page.html?query=new&sortOrder=ASC");
var returnUri = $"{uri.Scheme}://www.{uri.Authority}
{string.Join(string.Empty, uri.Segments)}{uri.Query}";

结果看起来像

Output: http://www.example.com/test/page.html?query=new&sortOrder=ASC

答案 5 :(得分:0)

您不需要RegEx,只需简单的替换即可:

List<Employee> employee=new ArrayList<Employee>();
static final  String[] mylist=new String[3];


employee.add(new Employee("Sofia","London","092237674643","Manager",30,800000));
employee.add(new Employee("Jones","Qwait","092013764551","CEO",33,20000000));
employee.add(new Employee("Kai","Korea","5243524541741","Staff",43,700000));

n=new String[]{"Wazma","Laiba","Kainat","Sana","Sara","Saba","Ayesha","Ali","Armeena","Ahmed"};
for(int i=0;i<employee.size();i++){
            mylist[i]=String.valueOf(employee.get(i));


        }
Iterator<Employee> itr=employee.iterator();
Employee emp;    
for(int j=0;j<mylist.length;j++){

             emp = itr.next();

             if(emp.getName().matches(mylist[j])) {
             System.out.println(mylist[j]);

                    }

答案 6 :(得分:0)

这是一个尝试的正则表达式:

(http)(s)?(:\/\/)[^www.][A-z0-9]+(.com|.gov|.org)

它会选择以下网址:

  • http://example.com
  • https://example.com
  • http://example.gov
  • https://example.gov
  • http://example.org
  • https://example.org

但不喜欢:

  • http://www.example.com
  • https://www.example.com

我更喜欢在可能的情况下使用显式扩展名(例如.com.gov.org),但如果它对您的用例有益,您也可以使用这样的内容:

(http)(s)?(:\/\/)[^www.][A-z0-9]+(.*){3}

然后我会用以下内容接近替换:

Regex r = new Regex(@"(http)(s)?(:\/\/)[^www.][A-z0-9]+(.*){3}");
string test = @"http://example.org";
if (r.IsMatch(test))
{
    Console.WriteLine(test.Replace("https://", "https://www."));
    Console.WriteLine(test.Replace("http://", "http://www."));
}

答案 7 :(得分:0)

现在大多数情况下,您都希望重定向到 www 和 https。 hankors 的回答很好,但需要两个重定向而不是一个,所以我重写了他的自定义规则,以便在需要时添加 www 和 https。结果只是一次重定向(如果您在 Azure 中关闭 https 重定向)。

    public class RedirectToHttpsWwwRule : IRule
{
    public void ApplyRule(RewriteContext context)
    {
        var req = context.HttpContext.Request;
        if (req.Host.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
        {
            context.Result = RuleResult.ContinueRules;
            return;
        }
        HostString wwwHost;

        if (req.IsHttps)
        {
            if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
            {
                context.Result = RuleResult.ContinueRules;
                return;
            }
            else
            {
                wwwHost = new HostString($"www.{req.Host.Value}");
            }
        }
        else
        {
            if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
            {
                wwwHost = new HostString(req.Host.Value);
            }
            else
            {
                wwwHost = new HostString($"www.{req.Host.Value}");
            }
        }

        string newUrl = UriHelper.BuildAbsolute("https", wwwHost, req.PathBase, req.Path, req.QueryString);
        var response = context.HttpContext.Response;
        response.StatusCode = 301;
        response.Headers[HeaderNames.Location] = newUrl;
        context.Result = RuleResult.EndResponse;
    }
}