【问题标题】:conditional nginx rewrite rule that exclude redirecting to www if www is already in request如果 www 已经在请求中,则排除重定向到 www 的条件 nginx 重写规则
【发布时间】:2021-08-28 15:52:08
【问题描述】:

我正在使用 nginx 来管理反向代理的多个域。

我想将所有http请求重定向到https

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

但是,我不确定如何使其以通用方式重写非 www 请求以重定向到 www,不包括重写那些在请求中已经包含 www 的请求,就好像我只是修改以下规则一样,当有人写时它会产生问题作为www.domain.com它 改写为www.www.domain.com

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://www.$host$request_uri;
}

请查看此图片以了解问题所在。

所以我需要一些条件来处理它。

【问题讨论】:

    标签: nginx nginx-reverse-proxy nginx-config


    【解决方案1】:

    请试试这个

     server {
            listen 80;
            listen [::]:80;
            server_name yourdomain.com www.yourdomain.com me.yourdomain.com;
            return 301 https://yourdomain.com$request_uri;
           }
    

    这会将所有 3 个域重写为 https://yourdomain.com

    我不确定我的答案。我现在无法对此进行测试。 请试试这个并回复评论

    【讨论】:

    • 我正在使用多个域名,这使我无法在规则中指定域。我需要一些通用的东西。而且,这条规则并不能解决目的,因为它不会重写到 www 域。
    • server_name yourdomain.com www.yourdomain.com me.yourdomain.com;在此处添加您的多个域并更改此“return 301 yourdomain.com$request_uri;”
    • 感谢您的帮助。发生的情况是:当访问者进入 www.domain.com 时,它会重定向到 www.www.domain.com。这就是我需要解决的问题。此外,有多个域,因此需要不需要我为每个域条目编写特定域的规则。
    【解决方案2】:

    如果你想要一个通用的方法,你可以使用map 指令(应该放在外面 server 块):

    map $host $basename {
        ~^www\.(.+)  $1;
        default      $host;
    }
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        return 301 https://$basename$request_uri;
    }
    

    更新 1

    看来我误读了您的问题(您需要将example.com 重定向到www.example.com,但我的回答正好相反),请尝试以下操作:

    map $host $basename {
        ~^www\.(.+)  $host;
        default      www.$host;
    }
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        return 301 https://$basename$request_uri;
    }
    

    更新 2

    OP 又问了一个问题:

    有没有办法排除我不想重写为www.static.example.com 的特定子域,如static.example.com

    是的,static 子域的重写可以通过以下 map 块来防止:

    map $host $basename {
        ~^(?:www|static)\..+  $host;
        default               www.$host;
    }
    

    如果要防止任何三元域名被改写,可以使用

    map $host $basename {
        ~[^.]+\.[^.]+\.[^.]+  $host;
        default               www.$host;
    }
    

    【讨论】:

    • 嗨,我试过这个,但是这不会将 domain.com 重写为 www.domain.com
    • 据我了解您的问题,您想要相反,将 www.domain.com 重写为 domain.com?
    • 谢谢,我试过了。但似乎example.com 重写为example.com,但example.com 未能重写为example.com。知道什么可以在这里提供帮助吗?
    • 另外,有没有办法排除我不想重写为 www.static.example.com 的特定子域,如 static.example.com?
    • https://example.com 重写为https://www.example.com,其中example.com 涉及多个域(例如domain1.comdomain2.com 等)是一项更复杂的任务。如果您想使用唯一的一个 server 块来执行此操作,则需要一个与这些域中的任何一个匹配的证书。虽然是possible,但您需要在certbot 命令行中列出所有域。你可以接受吗?
    【解决方案3】:

    非 www 到 www 和 https 重定向

    如果我理解正确,那么您想将非 www 强制为 www。并且您想强制所有请求到 https。此配置代码检查$host 是否以"www." 开头。如果没有,那么 nginx 将在 $host 之前添加 "www." 然后返回正确的 https 位置。它也适用于子域。

    server {
      if ($host !~* ^www\.) {
        # if host name starts with (case insensitive) "www."
        return 301 https://www.$host$request_uri;
      }
      if ($host ~* ^www\. ) {
        # if host name doesn't start with (case insensitive) "www."
        return 301 https://$host$request_uri;
      }
      listen 80 default_server;
      listen [::]:80 default_server;
      server_name _;
      return 404;
    }
    

    使用 Certbot 可能会更好

    您可以使用Certbot 自动生成您需要的代码。它还将帮助您管理证书并自动续订。但是 Certbot 不会将非 www 更改为 www,您必须编辑自动生成的配置以看起来像上面的配置。另一个区别是每个域都需要不同的配置块/文件,但不确定是否有必要。这是每个域的默认配置。

    server {
      if ($host = www.yourdomain.com) {
        return 301 https://$host$request_uri;
      } # managed by Certbot
    
    
      if ($host = yourdomain.com) {
        return 301 https://$host$request_uri;
      } # managed by Certbot
    
    
      listen 80;
      listen [::]:80;
      server_name yourdomain.com www.yourdomain.com;
      return 404; # managed by Certbot
    }
    

    我认为最好将每个域和子域的配置文件分开,并使用默认的 Certbot 格式,直到您对 Nginx 有了更多了解。这样,您可以非常轻松地禁用非 www 到 www 的重定向。上面来自 Certbot 的默认代码将是您在这种情况下不想重定向时放置的代码。从长远来看,这对我来说更有意义,但我理解当用户更熟悉 www 或网站的其他部分可能需要 www 时。

    【讨论】:

    • 第二个条件规则不应该有https://www.$host$request_uri而不是https://$host$request_uri吗?另请参阅 https://example.com 不会重定向到 https://www.example.com。请帮忙
    • 我测试过了。第一个块有效。你可以用那个替换你的服务器配置块。 www.$host 的一部分,因此不需要将其添加到 return 语句中。第二个代码块需要您修复代码的其他部分。确保你阅读了我写的所有内容。
    • 当然。我没明白你所说的“第二个代码块需要你修复代码的其他部分”是什么意思?
    • 您不能使用第二个代码块来获得您想要的结果。我解释了它的作用,你应该更多地了解为什么它自己可能会更好。
    猜你喜欢
    • 1970-01-01
    • 2017-05-09
    • 2020-11-28
    • 2016-06-16
    • 2019-02-04
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 2012-04-11
    相关资源
    最近更新 更多