问题描述
我正在使用nginx on Rackspace cloud following a tutorial并已搜索过网络,到目前为止无法进行排序。
由于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。
最佳方法
HTTP解决方案
在documentation中,“正确的方法是为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://服务器是high-traffic SSL付款服务器,因此我最初没有在解决方案中包含https://
:我们不混合使用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标记,因为它完全是烫发重定向和移动。禁止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;
}
}
次佳方法
实际上,您甚至不需要重写。
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
。为什么?因为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上侦听(默认),并且侦听选项不包含ssl
关键字,则$scheme
变量将仅包含http
。不使用该变量将不会获得任何性能。
请注意,如果使用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...
}
我想您现在可以自己想象具有这种模式的其他化合物。
第三种方法
您可能会发现要对更多域使用相同的配置。
以下代码段会在任何域之前删除www:
if ($host ~* ^www\.(.*)$) {
rewrite / $scheme://$1 permanent;
}
第四种方法
您需要两个服务器块。
将它们放入您的配置文件中,例如/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记录对。
第五种方法
这是将多个www转换为no-www服务器名称的方法(我将其用于子域):
server {
server_name
"~^www\.(sub1.example.com)$"
"~^www\.(sub2.example.com)$"
"~^www\.(sub3.example.com)$";
return 301 $scheme://$1$request_uri ;
}
第六种方法
此解决方案来自我的个人经验。我们使用了几个Amazon S3存储桶和一个服务器将non-www
重定向到www
域名以匹配S3 “Host” header policy。
我对nginx服务器使用了以下配置:
server {
listen 80;
server_name ~^(?!www\.)(?<domain>.+)$;
return 301 $scheme://www.$domain$request_uri;
}
这匹配指向除www.
以外的所有指向服务器的域名,并重定向到www.<domain>
。以相同的方式,您可以执行从www
到non-www
的反向重定向。
第七种方法
在没有hard-coded域的情况下,我结合了所有简单答案中的最佳方法。
301从非www永久重定向到www(HTTP或HTTPS):
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;
}
第八种方法
-
最佳实践:带硬编码的
server_name
的单独server
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
}
-
在
server_name
中使用正则表达式
如果您有多个站点,并且不希望获得最高的性能,但是希望每个站点在www.
前缀方面都具有相同的策略,则可以使用正则表达式。使用单独的server
的最佳实践仍然有效。
请注意,如果您使用https,则此解决方案会很棘手,因为如果您希望此方法正常运行,则必须具有一个证书来覆盖所有域名。
适用于所有站点的专用单个server
中的非www
到正则表达式的www
:
server {
server_name ~^(?!www\.)(?<domain>.+)$;
return 301 $scheme://www.$domain$request_uri;
}
适用于所有站点的专用单个server
中的www
到带有正则表达式的非www
:
server {
server_name ~^www\.(?<domain>.+)$;
return 301 $scheme://$domain$request_uri;
}
www
到带有正则表达式的非www
(专用于某些站点)在专用server
中:
可能有必要将正则表达式限制为仅覆盖两个域,然后可以使用类似这样的方法来仅匹配www.example.org
,www.example.com
和www.subdomain.example.net
:
server {
server_name ~^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$;
return 301 $scheme://$domain$request_uri;
}
使用nginx测试正则表达式
您可以测试正则表达式与系统上的pcretest
是否可以正常工作,这与您的nginx用于正则表达式的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 server name regex when “Host” header has a trailing dot,您不必担心尾随点或大小写,因为nginx已经处理了它。
-
将
if
撒在现有的server
/HTTPS中:
最终解决方案通常不被视为最佳实践,但是,它仍然可以正常工作。
实际上,如果您使用的是HTTPS,则最终的解决方案可能最终更易于维护,因为您不必在不同的server
定义之间使用copy-paste一大堆ssl指令,而只需将代码段放入所需的服务器,从而使调试和维护站点变得更加容易。
非www
到www
:
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;
}
参考文献:
第九种方法
将非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 ;
}
第十种方法
尝试这个
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;
}