536

我正在按照教程在 Rackspace 云上使用 nginx,并且已经搜索了网络,但到目前为止无法对其进行排序。

出于 SEO 和其他原因,我希望 www.mysite.com 在 .htaccess 中正常访问 mysite.com。

我的/etc/nginx/sites-available/www.example.com.vhost配置:

server {
       listen 80;
       server_name www.example.com example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://example.com$request_uri permanent;
       }

我也试过

server {
       listen 80;
       server_name example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://example.com$request_uri permanent;
       }

我也试过。第二次尝试都给出了重定向循环错误。

if ($host = 'www.example.com' ) {
rewrite ^ http://example.com$uri permanent;
}

我的 DNS 设置为标准:

site.com 192.192.6.8 A type at 300 seconds
www.site.com 192.192.6.8 A type at 300 seconds

(示例 IP 和文件夹已用于示例并在将来帮助人们)。我使用 Ubuntu 11。

4

17 回答 17

819

HTTP 解决方案

文档中,“正确的方法是为 example.org 定义一个单独的服务器”:

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

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

HTTPS 解决方案

对于那些想要解决方案的人,包括https://...

server {
        listen 80;
        server_name www.domain.com;
        # $scheme will get the http protocol
        # and 301 is best practice for tablet, phone, desktop and seo
        return 301 $scheme://domain.com$request_uri;
}

server {
        listen 80;
        server_name domain.com;
        # here goes the rest of your config file
        # example 
        location / {

            rewrite ^/cp/login?$ /cp/login.php last;
            # etc etc...

        }
}

注意:我最初没有包含https://在我的解决方案中,因为我们使用负载平衡器并且我们的 https:// 服务器是高流量 SSL 支付服务器:我们不混合使用 https:// 和 http://。


要检查 nginx 版本,请使用nginx -v.

使用 nginx 重定向从 url 中去除 www

server {
    server_name  www.domain.com;
    rewrite ^(.*) http://domain.com$1 permanent;
}

server {
    server_name  domain.com;
    #The rest of your configuration goes here#
}

所以你需要有两个服务器代码。

使用 nginx 重定向将 www 添加到 url

如果你需要的是相反的,从 domain.com 重定向到 www.domain.com,你可以使用这个:

server {
    server_name  domain.com;
    rewrite ^(.*) http://www.domain.com$1 permanent;
}

server {
    server_name  www.domain.com;
    #The rest of your configuration goes here#
}

正如你可以想象的那样,这正好相反,工作方式与第一个示例相同。这样,您就不会降低 SEO 标记,因为它是完整的烫发重定向和移动。强制 no WWW 并显示目录!

下面显示了我的一些代码以获得更好的视图:

server {
    server_name  www.google.com;
    rewrite ^(.*) http://google.com$1 permanent;
}
server {
       listen 80;
       server_name google.com;
       index index.php index.html;
       ####
       # now pull the site from one directory #
       root /var/www/www.google.com/web;
       # done #
       location = /favicon.ico {
                log_not_found off;
                access_log off;
       }
}
于 2011-10-31T19:18:07.033 回答
424

其实你甚至不需要重写。

server {
    #listen 80 is default
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {
    #listen 80 is default
    server_name example.com;
    ## here goes the rest of your conf...
}

因为我的回答是得到越来越多的赞成票,但以上也是如此。你不应该rewrite在这种情况下使用 a 。为什么?因为 nginx 必须处理并开始搜索。如果您使用return(应该在任何 nginx 版本中都可用),它会直接停止执行。这在任何情况下都是首选。

将非 SSL 和 SSL 都重定向到它们的非 www 对应物:

server {
    listen               80;
    listen               443 ssl;
    server_name          www.example.com;
    ssl_certificate      path/to/cert;
    ssl_certificate_key  path/to/key;

    return 301 $scheme://example.com$request_uri;
}

server {
    listen               80;
    listen               443 ssl;
    server_name          example.com;
    ssl_certificate      path/to/cert;
    ssl_certificate_key  path/to/key;

    # rest goes here...
}

仅当您的服务器仅侦听端口 80(默认)并且侦听选项不包含关键字时,该$scheme变量才会包含。不使用该变量不会获得任何性能。httpssl

请注意,如果您使用 HSTS,则需要更多的服务器块,因为 HSTS 标头不应通过非加密连接发送。因此,您需要带有重定向的未加密服务器块和带有重定向和 HSTS 标头的加密服务器块。

将所有内容重定向到 SSL(在 UNIX 上使用 IPv4、IPv6、SPDY 进行个人配置...):

#
# Redirect all www to non-www
#
server {
    server_name          www.example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:80;
    listen               *:443 ssl spdy;
    listen               [::]:80 ipv6only=on;
    listen               [::]:443 ssl spdy ipv6only=on;

    return 301 https://example.com$request_uri;
}

#
# Redirect all non-encrypted to encrypted
#
server {
    server_name          example.com;
    listen               *:80;
    listen               [::]:80;

    return 301 https://example.com$request_uri;
}

#
# There we go!
#
server {
    server_name          example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:443 ssl spdy;
    listen               [::]:443 ssl spdy;

    # rest goes here...
}

我想您现在可以自己想象具有这种模式的其他化合物。

更多我的配置?去这里这里

于 2012-07-31T04:58:55.247 回答
58
  1. 最佳实践:单独server使用硬编码server_name

nginx 的最佳实践是使用单独server的重定向进行这样的重定向(不与server您的主配置共享),对所有内容进行硬编码,并且根本不使用正则表达式。

如果您使用 HTTPS,可能还需要对域进行硬编码,因为您必须预先知道您将提供哪些证书。

server {
    server_name www.example.com;
    return  301 $scheme://example.com$request_uri;
}
server {
    server_name www.example.org;
    return  301 $scheme://example.org$request_uri;
}
server {
    server_name example.com example.org;
    # real configuration goes here
}

  1. 在内部使用正则表达式server_name

如果您有多个站点,并且不关心最高性能,但希望每个站点在www.前缀方面都具有相同的策略,那么您可以使用正则表达式。使用单独的最佳实践server仍然有效。

请注意,如果您使用 https,此解决方案会变得很棘手,因为如果您希望它正常工作,您必须拥有一个证书来覆盖您的所有域名。


wwwwwww/ 正则表达式在所有站点的专用单server

server {
    server_name ~^(?!www\.)(?<domain>.+)$;
    return  301 $scheme://www.$domain$request_uri;
}

www到所有站点www的专用单中的非w/ 正则表达式:server

server {
    server_name ~^www\.(?<domain>.+)$;
    return  301 $scheme://$domain$request_uri;
}

www仅在某些站点专用于非wwww/ 正则表达式:server

可能有必要将正则表达式限制为仅涵盖几个域,然后您可以使用类似这样的内容仅匹配www.example.org,www.example.comwww.subdomain.example.net

server {
    server_name ~^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$;
    return  301 $scheme://$domain$request_uri;
}

使用 nginx 测试正则表达式

您可以测试正则表达式在您的系统上是否按预期工作,这与您的 nginx 将用于正则表达式的库pcretest完全相同:pcre

% pcretest 
PCRE version 8.35 2014-04-04

  re> #^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$#
data> test
No match
data> www.example.org
 0: www.example.org
 1: example.org
data> www.test.example.org
No match
data> www.example.com
 0: www.example.com
 1: example.com
data> www.subdomain.example.net
 0: www.subdomain.example.net
 1: subdomain.example.net
data> subdomain.example.net
No match
data> www.subdomain.example.net.
No match
data> 

请注意,您不必担心尾随点或大小写,因为 nginx 已经处理了它,根据nginx 服务器名称正则表达式,当“主机”标头有一个尾随点时


  1. if在现有server/HTTPS 中:

这个最终解决方案通常不被认为是最佳实践,但是,它仍然有效并且可以完成工作。

事实上,如果您使用的是 HTTPS,那么最终的解决方案可能最终更易于维护,因为您不必在不同定义之间复制粘贴一大堆 ssl 指令server,而可以只将代码片段放入所需的服务器,从而更容易调试和维护您的站点。


wwwwww

if ($host ~ ^(?!www\.)(?<domain>.+)$) {
    return  301 $scheme://www.$domain$request_uri;
}

www到非www

if ($host ~ ^www\.(?<domain>.+)$) {
    return  301 $scheme://$domain$request_uri;
}

硬编码单个首选域

如果您想要更高的性能,以及单个server可能使用的多个域之间的一致性,则显式硬编码单个首选域可能仍然有意义:

if ($host != "example.com") {
    return  301 $scheme://example.com$request_uri;
}

参考:

于 2019-01-23T00:37:54.540 回答
45

您可能会发现要对更多域使用相同的配置。

以下代码段在任何域之前删除 www:

if ($host ~* ^www\.(.*)$) {
    rewrite / $scheme://$1 permanent;
}
于 2015-05-14T14:46:18.863 回答
29

您需要两个服务器块。

将这些放入您的配置文件中,例如/etc/nginx/sites-available/sitename

假设您决定使用http://example.com作为主要地址。

您的配置文件应如下所示:

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

        # this is the main server block
        # insert ALL other config or settings in this server block
}

第一个服务器块将保存重定向任何带有“www”前缀的请求的指令。它侦听带有“www”前缀的 URL 请求并进行重定向。

它什么也不做。

第二个服务器块将保存您的主地址——您要使用的 URL。所有其他设置都放在此处,例如root, index,location等。检查默认文件以获取可以包含在服务器块中的这些其他设置。

服务器需要两条 DNS A 记录。

Name: @ IPAddress: your-ip-address (for the example.com URL)

Name: www IPAddress: your-ip-address (for the www.example.com URL)

对于 ipv6,使用 your-ipv6-address 创建一对 AAAA 记录。

于 2016-08-28T13:35:51.610 回答
23

以下是如何为多个 www 到 no-www 服务器名称执行此操作(我将其用于子域):

server {
        server_name 
             "~^www\.(sub1.example.com)$"
             "~^www\.(sub2.example.com)$"
             "~^www\.(sub3.example.com)$";
         return 301 $scheme://$1$request_uri ;
}
于 2014-12-10T17:00:29.687 回答
19

我结合了所有简单答案中最好的,没有硬编码的域。

从非 www 到 www(HTTP 或 HTTPS)的 301 永久重定向:

server {
    if ($host !~ ^www\.) {
        rewrite ^ $scheme://www.$host$request_uri permanent;
    }

    # Regular location configs...
}

如果您更喜欢非 HTTPS、非 www 而不是 HTTPS,同时 www 重定向:

server {
    listen 80;

    if ($host !~ ^www\.) {
        rewrite ^ https://www.$host$request_uri permanent;
    }

    rewrite ^ https://$host$request_uri permanent;
}
于 2018-04-25T02:56:30.710 回答
16

这个解决方案来自我的个人经验。我们使用多个 Amazon S3 存储桶和一台服务器重定向non-wwwwww域名以匹配S3“主机”标头策略

我对nginx服务器使用了以下配置:

server {
    listen 80;
    server_name ~^(?!www\.)(?<domain>.+)$;
    return 301 $scheme://www.$domain$request_uri;
}

这匹配指向服务器的所有域名,以 but 开头www.并重定向到www.<domain>. 以同样的方式,您可以从wwwto进行相反的重定向non-www

于 2015-10-16T15:44:33.490 回答
12

试试这个

    if ($host !~* ^www\.){
        rewrite ^(.*)$ https://www.yoursite.com$1;
    }

其他方式:Nginx no-www 到 www

server {
  listen       80;
  server_name  yoursite.com;
  root /path/;
  index index.php;
  return       301 https://www.yoursite.com$request_uri;
}

和 www 到 no-www

server {
  listen       80;
  server_name  www.yoursite.com;
  root /path/;
  index index.php;
  return       301 https://yoursite.com$request_uri;
}
于 2013-10-08T17:18:22.863 回答
11

将非 www 重定向到 www

对于单域:

server {
        server_name example.com;
        return 301 $scheme://www.example.com$request_uri;
}

对于所有域:

server {
        server_name "~^(?!www\.).*" ;
        return 301 $scheme://www.$host$request_uri;
}

将 www 重定向到非 www 对于单个域:

server {
        server_name www.example.com;
        return 301 $scheme://example.com$request_uri;
}

对于所有域:

server {
         server_name "~^www\.(.*)$" ;
         return 301 $scheme://$1$request_uri ;
}
于 2017-07-25T07:19:11.600 回答
9

独特的格式:

server {
  listen 80;
  server_name "~^www\.(.*)$" ;
  return 301 https://$1$request_uri ;
}
于 2015-02-19T16:01:47.947 回答
6

如果您不想对域名进行硬编码,可以使用此重定向块。没有前导 www 的域被保存为$domain可以在重定向语句中重用的变量。

server {
    ...
    # Redirect www to non-www
    if ( $host ~ ^www\.(?<domain>.+) ) {
       rewrite ^/(.*)$ $scheme://$domain/$1;
    }
}

REF:在 nginx 中使用正则表达式重定向子域

于 2019-02-25T01:39:10.520 回答
5
location / { 
    if ($http_host !~ "^www.domain.com"){ 
        rewrite ^(.*)$ $scheme://www.domain.com/$1 redirect; 
    } 
}
于 2016-05-23T17:09:50.897 回答
3

不知道是否有人注意到返回 301 可能是正确的,但浏览器对此感到窒息

rewrite ^(.*)$ https://yoursite.com$1; 

比:

return 301 $scheme://yoursite.com$request_uri;
于 2014-06-04T01:33:15.613 回答
2

鬼博客

为了使 nginx 推荐的方法与return 301 $scheme://example.com$request_uri;Ghost 一起使用,您需要在主服务器块中添加:

proxy_set_header    X-Real-IP           $remote_addr;
proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
proxy_set_header    Host                $http_host;
proxy_set_header    X-Forwarded-Proto   $scheme;
proxy_set_header    X-NginX-Proxy       true;

proxy_pass_header   X-CSRF-TOKEN;
proxy_buffering     off;
proxy_redirect      off;  
于 2014-11-15T15:58:51.257 回答
0
if ($host ~* ^www.example.com$) {
    return 301 $scheme://example.com$request_uri;
}
于 2016-07-10T21:36:31.033 回答
-6

如果您无法使其正常工作,您可能需要添加服务器的 IP 地址。例如:

server {
listen XXX.XXX.XXX.XXX:80;
listen XXX.XXX.XXX.XXX:443 ssl;
ssl_certificate /var/www/example.com/web/ssl/example.com.crt;
ssl_certificate_key /var/www/example.com/web/ssl/example.com.key;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}

其中 XXX.XXX.XXX.XXX 是 IP 地址(显然)。

注意:必须定义 ssl crt 和 key location 才能正确重定向 https 请求

进行更改后不要忘记重新启动 nginx:

service nginx restart
于 2013-10-28T19:14:25.440 回答