本文最后更新于 1028 天前,如遇到任何问题欢迎在评论区留言呀!
为什么使用 301 重定向
首先,我们先来说一下301 重定向(也叫永久重定向,英文:permanent redirect)能干什么?
301 重定向:当用户访问某一个 URL 时,web 服务器被设置自动跳转到另外一个 URL,此时返回客户端的返回码为301。
我们在以下情况会用到301 重定向:
- 为了用户访问方便,域名解析时同时添加了
A 记录中的www,和@,这样用户不用输入www就可以找到我们的网页,但也带来了问题,毕竟他们是两个不同 URL,搜索引擎收录的时候会认为是两个网页互相抄袭,不利于收录(毕竟两个不同的地址内容完全一样,不就是抄袭嘛),而且统计网站访问数的时候,也是带www的 URL 和不带的是作为两个,不利于统计。 - 如果你更换了域名,希望别人还能找到你,那就更要做
301 重定向了,就像你开个小卖铺换了个地址,当然要在旧的店铺门口写上,本店已搬往 xxx。 
如何在 nginx 上实现 301 重定向
语法
只需在 nginx 的配置文件nginx.conf中加上一行
return 301 具体的网址;
填在哪里
填在server块里即可,你可以把每一个server想象成一台 web 服务器。
具体怎么填
我们先来介绍一下填写网址必不可少的 nginx 的全局变量
$host 访问请求中的主机头部,也就是常说的网址
$request_uri 请求中 host 后面的那一大串东西
$scheme 请求的协议,比如 http,ftp 等
$server_addr 服务器 IP 地址
$server_name 服务器主机名
$server_port 访问服务器的端口号
对于刚刚的第一种情况,我们可以再添加一个server监听443端口,将不带 www 的请求转到带 www 的请求:
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 的网址。
对于刚刚的第二种情况,我们可以这样写
server{
    listen      80 443;
    server_name old.name www.old.name;
    return 301 $scheme://www.new.name$request_uri;
}
注意上面的域名替换成自己的就可以了。
从性能方面考虑
对于第二种情况没什么好说的,无脑重定向即可。对于第一种情况的讨论,我看网上大概有这么几种方式实现。
其一
采用rewrite结合正则表达式来实现的,nginx 官方对此的评价为:
This is a wrong, cumbersome, and ineffective way.
这样会让我们的 web 变得低效,当然个人博客这种小网站当然不明显。
其二
另外一种是只用一个server块监听443端口,用if做条件判断,配置文件这么写
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效率高。