在nginx上实现301重定向 统一域名

1. 为什么使用301重定向

首先,我们先来说一下301重定向(也叫永久重定向,英文:permanent redirect)能干什么?

301重定向:当用户访问某一个URL时,web服务器被设置自动跳转到另外一个URL,此时返回客户端的返回码为301

我们在以下情况会用到301重定向

  1. 为了用户访问方便,域名解析时同时添加了A记录中的www,和@,这样用户不用输入www就可以找到我们的网页,但也带来了问题,毕竟他们是两个不同URL,搜索引擎收录的时候会认为是两个网页互相抄袭,不利于收录(毕竟两个不同的地址内容完全一样,不就是抄袭嘛),而且统计网站访问数的时候,也是带www的URL和不带的是作为两个,不利于统计。
  2. 如果你更换了域名,希望别人还能找到你,那就更要做301重定向了,就像你开个小卖铺换了个地址,当然要在旧的店铺门口写上,本店已搬往xxx。

2. 如何在nginx上实现301重定向

2.1. 语法

只需在nginx的配置文件nginx.conf中加上一行

1
return 301 具体的网址;

2.2. 填在哪里

填在server块里即可,你可以把每一个server想象成一台web服务器。

2.3. 具体怎么填

我们先来介绍一下填写网址必不可少的nginx的全局变量

1
2
3
4
5
6
$host 访问请求中的主机头部,也就是常说的网址
$request_uri 请求中host后面的那一大串东西
$scheme 请求的协议,比如http,ftp等
$server_addr 服务器IP地址
$server_name 服务器主机名
$server_port 访问服务器的端口号

对于刚刚的第一种情况,我们可以再添加一个server监听443端口,将不带www的请求转到带www的请求:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 443;
server_name shenxiaojian.com;
return 301 https://www.shenxiaojian.com$request_uri;
}

server {
listen 443;
server_name www.shenxiaojian.com;
...
}

这样就表示如果访问的是我不带www的网址会自动跳到带www的网址。

对于刚刚的第二种情况,我们可以这样写

1
2
3
4
5
server{
listen 80 443;
server_name old.name www.old.name;
return 301 $scheme://www.new.name$request_uri;
}

注意上面的域名替换成自己的就可以了。

2.4. 从性能方面考虑

对于第二种情况没什么好说的,无脑重定向即可。对于第一种情况的讨论,我看网上大概有这么几种方式实现。

2.4.1. 其一

采用rewrite结合正则表达式来实现的,nginx官方对此的评价为:

This is a wrong, cumbersome, and ineffective way.

这样会让我们的web变得低效,当然个人博客这种小网站当然不明显。

2.4.2. 其二

另外一种是只用一个server块监听443端口,用if做条件判断,配置文件这么写

1
2
3
4
5
6
7
8
server{
listen 443;
server_name www.shenxiaojian.com shenxiaojian.com;
if ( $host != www.shenxiaojian.com ){
return 301 $scheme://www.shenxiaojian.com$request_uri;
}
...
}

这样带来的问题是,无论访问的网址带不带www,都要去判断一次,而我们这一部分开头给出的那种,如果带www的是无需判断的,当然你可以说,两个server来找哪一个的时候,不也是要判断吗?但是我想说,那是软件内部的判断,其优化要比我们自己用if效率高。