我正在使用 nginx on Rackspace cloud following a tutorial 并且已经搜索了网络,但到目前为止无法对其进行排序。
出于 SEO 和其他原因,我希望 www.mysite.example
在 .htaccess 中正常转到 mysite.example
。
我的 /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.example 192.192.6.8 A type at 300 seconds
www.site.example 192.192.6.8 A type at 300 seconds
(示例 IP 和文件夹已用于示例并在将来帮助人们)。我使用 Ubuntu 11。
Dashboard > Settings > General Settings
并确保 WordPress 地址/站点地址 URL 中没有 www
。无论您如何配置您的 nginx,如果您在这些 URL 中有 www,它将被重定向到其中包含 www 的那个。
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.example;
# $scheme will get the http protocol
# and 301 is best practice for tablet, phone, desktop and seo
return 301 $scheme://domain.example$request_uri;
}
server {
listen 80;
server_name domain.example;
# 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.example;
rewrite ^(.*) http://domain.example$1 permanent;
}
server {
server_name domain.example;
#The rest of your configuration goes here#
}
所以你需要有两个服务器代码。
使用 Nginx 重定向将 www 添加到 URL
如果您需要的是相反的,从 domain.example
重定向到 www.domain.example
,您可以使用这个:
server {
server_name domain.example;
rewrite ^(.*) http://www.domain.example$1 permanent;
}
server {
server_name www.domain.example;
#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;
}
}
其实你甚至不需要重写。
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...
}
我想您现在可以自己想象具有这种模式的其他化合物。
最佳实践:带有硬编码 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
}
在 server_name 中使用正则表达式
如果您有多个站点,并且不关心最高性能,但希望每个站点都对 www.
前缀具有相同的策略,那么您可以使用正则表达式。使用单独的 server
的最佳做法仍然有效。
请注意,如果您使用 https,此解决方案会变得很棘手,因为如果您希望它正常工作,您必须拥有一个证书来覆盖您的所有域名。
非 www 到 www w/ 正则表达式在所有站点的专用单一服务器中:
server {
server_name ~^(?!www\.)(?<domain>.+)$;
return 301 $scheme://www.$domain$request_uri;
}
www 到非 www w/ 正则表达式在所有站点的专用单个服务器中:
server {
server_name ~^www\.(?<domain>.+)$;
return 301 $scheme://$domain$request_uri;
}
www 到非 www w/ regex 仅适用于某些站点的专用服务器:
可能需要将正则表达式限制为仅涵盖几个域,然后您可以使用类似的内容仅匹配 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 已经按照 nginx server name regex when "Host" header has a trailing dot 处理了它。
如果在现有服务器/HTTPS 中,则撒上:
这个最终解决方案通常不被认为是最佳实践,但是,它仍然有效并且可以完成工作。
事实上,如果您使用的是 HTTPS,那么最终的解决方案可能会更容易维护,因为您不必在不同的 server
定义之间复制粘贴一大堆 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;
}
参考:
http://nginx.org/r/server_name
http://nginx.org/r/return
http://nginx.org/en/docs/http/server_names.html
您可能会发现要对更多域使用相同的配置。
以下代码段在任何域之前删除 www:
if ($host ~* ^www\.(.*)$) {
rewrite / $scheme://$1 permanent;
}
http
更改为 $scheme
return ...
和 rewrite ... last
”。性能问题的任何更新链接?
您需要两个服务器块。
将这些放入您的配置文件中,例如 /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 ;
}
我结合了所有简单答案中最好的,没有硬编码的域。
从非 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;
}
这个解决方案来自我的个人经验。我们使用多个 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
的反向重定向。
listen 80
之后,您需要添加 listen 443 ssl
,然后是 ssl_certificate
和 ssl_certificate_key
指令。
listen 443 ssl
。这不会工作,并导致一些严重的头痛。
尝试这个
if ($host !~* ^www\.){
rewrite ^(.*)$ https://www.yoursite.example$1;
}
其他方式:Nginx no-www 到 www
server {
listen 80;
server_name yoursite.example;
root /path/;
index index.php;
return 301 https://www.yoursite.example$request_uri;
}
和 www 到 no-www
server {
listen 80;
server_name www.yoursite.example;
root /path/;
index index.php;
return 301 https://yoursite.example$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 ;
}
80
和 443
吗?
listen
指令的情况下工作(nginx 1.4.6)。
独特的格式:
server {
listen 80;
server_name "~^www\.(.*)$" ;
return 301 https://$1$request_uri ;
}
server {
server_name "~^www\.(.*)$" ;
return 301 $scheme://$1$request_uri ;
}
如果您不想对域名进行硬编码,可以使用此重定向块。没有前导 www 的域被保存为变量 $domain
,可以在重定向语句中重用。
server {
...
# Redirect www to non-www
if ( $host ~ ^www\.(?<domain>.+) ) {
rewrite ^/(.*)$ $scheme://$domain/$1;
}
}
参考:Redirecting a subdomain with a regular expression in nginx
location / {
if ($http_host !~ "^www.domain.example"){
rewrite ^(.*)$ $scheme://www.domain.example$1 redirect;
}
}
$scheme://www.domain.com$1
避免双斜杠
不知道是否有人注意到返回 301 可能是正确的,但浏览器对此感到窒息
rewrite ^(.*)$ https://yoursite.example$1;
比:
return 301 $scheme://yoursite.example$request_uri;
鬼博客
为了使带有 return 301 $scheme://example.com$request_uri;
的 nginx 推荐方法与 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;
if ($host ~* ^www.example.com$) {
return 301 $scheme://example.com$request_uri;
}
我的配置是 - Nginx + tomcat 9 + Ubuntu 20.04 + spring boot app 以上所有答案都对我不起作用 - Nginx 文件中的上游符号也不起作用 - 所以我更改了我的设置
感谢上帝的 certbot - 这个工具非常有用,它为您的站点生成基本文件,然后我添加了我的更改 - 将 https://www.example.com
、http://www.example.com
重定向到只有一个 https://example.com
server {
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
}
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080; # This is upstream name, note the variable $scheme in it
proxy_redirect off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
如果您无法使其正常工作,您可能需要添加服务器的 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
/etc/init.d/nginx reload
您也可以reload
服务器,这不会导致任何停机。
不定期副业成功案例分享
return 301 $scheme://domain.com$request_uri;
。无需捕获任何模式,请参阅 Nginx pitfalls