Nginx将非www前缀域重写为www-prefixed域

时间:2009-10-27 07:31:05

标签: nginx rewrite url-rewriting

我看到Nginx HttpRewriteModule documentation有一个例子,可以将以www为前缀的域重写为非www前缀域:

if ($host ~* www\.(.*)) {
  set $host_without_www $1;
  rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/foo', not 'www.mydomain.com/foo'
}

如何进行反向 - 将非www前缀域重写为以www为前缀的域?我想也许我可以做类似下面的事情,但是Nginx不喜欢嵌套的if语句。

if ($host !~* ^www\.) {                       # check if host doesn't start with www.
    if ($host ~* ([a-z0-9]+\.[a-z0-9]+)) {    # check host is of the form xxx.xxx (i.e. no subdomain)
        set $host_with_www www.$1;
        rewrite ^(.*)$ http://$host_with_www$1 permanent;
    }
}

此外,我希望这适用于任何域名,而无需明确告知Nginx重写domain1.com - > www.domain1.com,domain2.com - > www.domain2.com等,因为我有大量的域要重写。

7 个答案:

答案 0 :(得分:62)

As noted in the Nginx documentation, you should avoid using the if directive in Nginx where possible,因为只要您的配置中有if,您的服务器就需要评估每个请求,以决定是否匹配if

更好的解决方案是多个服务器指令。

server {
        listen 80;
        server_name website.com;
        return 301 $scheme://www.website.com$request_uri;
}

server {
        listen 80;
        server_name www.website.com;
        ... 
}

如果您尝试为启用SSL(HTTPS)的网站提供服务,则可以选择三种不同的选项。

  1. 设置多个IP地址,让每个服务器指令监听自己的IP(如果这是您的选项,则为不同的端口)。此选项需要 website.com www.website.com 的SSL证书,因此您要么拥有通配符证书,要么拥有UNI证书(多个域)或者只是两个不同的证书。
  2. 在应用程序中进行重写。
  3. 使用可怕的if指令。
  4. There is also an option to use SNI, but I'm not sure this is fully supported as of now

答案 1 :(得分:15)

if ($host !~* ^www\.) {
    rewrite ^(.*)$ http://www.$host$1 permanent;
}

答案 2 :(得分:13)

嗯,我想我真的不需要外部的“if”语句,因为我只是检查xxx.xxx格式的域名。以下适用于我,虽然它不健壮。如果有更好的解决方案,请告诉我。

    if ($host ~* ^([a-z0-9\-]+\.(com|net|org))$) {
        set $host_with_www www.$1;
        rewrite ^(.*)$ http://$host_with_www$1 permanent;
    }

编辑:在正则表达式中添加了连字符,因为它是主机名中的有效字符。

答案 3 :(得分:6)

if ($host ~* ^[^.]+\.[^.]+$) {
    rewrite ^(.*)$ http://www.$host$1 permanent;
}

只能获得有效的主机名,因为请求永远不会进入您的服务器,因此不需要构建自己的验证逻辑。

答案 4 :(得分:4)

nginx文档警告不要使用if进行重写。请参阅此处的链接:http://wiki.nginx.org/Pitfalls#Server_Name

答案 5 :(得分:1)

没有条件的HTTP和HTTPS:

server {
    listen          80;
    listen          443;
    server_name     website.com;

    return 301 $scheme://www.website.com$request_uri;
}
server {
    listen          80;
    listen          443 default_server ssl;
    server_name     www.website.com;

    # Your config goes here #
}

答案 6 :(得分:0)

多个域的解决方案,对我来说是nginx 1.17:

server {
        listen                                80;
        server_name                           .example.com;

        set $host_with_www                 $host;

        if ($host !~* www\.(.*)) {
            set $host_with_www www.$host;
        }

        return                                301 https://$host_with_www$request_uri;
}

在此配置示例中,如果您不想重写,还可以在HTTPS上重写HTTP —用return字符串中的http://替换https://。

如果要保留协议,请使用$scheme变量。