Nginx 30x 重定向


为何要使用301重定向
在网站建设中需要网页重定向的情况很多:如网页目录结构变动,网页重命名、网页的扩展名改变、网站域名改变等。如果不做重定向,用户的收藏和搜索引擎数据库中的旧地址只能让访客得到一个404错误信息页面,给用户带来不友好的体验。301重定向不仅能使页面实现自动跳转,对于搜索引擎来说,也可能可以传递PR值。
rewrite命令
nginx的rewrite相当于apache的rewrite rule(大多数情况下可以把原有apache的rewrite规则加上引号就可以直接使用),它可以用在server,location和if条件判断块中,命令格式如下:
rewrite 正则表达式 替换目标 flag标记
flag标记可以用以下几种格式:
last – 基本上都用这个Flag。
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301
例如下面这段设定nginx将某个目录下面的文件重定向到另一个目录,$2对应第二个括号(.*)中对应的字符串:
location /download/ {
rewrite ^(/download/.*)/m/(.*)\..*$ $1/nginx-rewrite/$2.gz break;
}
nginx重定向的if条件判断
在server和location两种情况下可以使用nginx的if条件判断,条件可以为以下几种:
正则表达式
匹配判断
~ 为区分大小写匹配; !~为区分大小写不匹配
~* 为不区分大小写匹配;!~为不区分大小写不匹配
例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /nginx-ie/$1 break;
}
文件和目录判断
-f和!-f判断是否存在文件
-d和!-d判断是否存在目录
-e和!-e判断是否存在文件或目录
-x和!-x判断文件是否可执行
例如下面设定nginx在文件和目录不存在的时候重定向:
if (!-e $request_filename) {
proxy_pass http://127.0.0.1/;
}
return
返回http代码,例如设置nginx防盗链:
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked http://www.freeoa.net/ http://www.google.com/;
if ($invalid_referer) {
return 404;
}
}
set
设置nginx变量
301重定向方法
进行了301重定向,把www.freeoa.net和freeoa.net合并,并把之前的域名也一并合并,有两种实现方法。
第一种方法是判断nginx核心变量host:
server {
server_name www.freeoa.net freeoa.net;
if ($host != 'www.freeoa.net' ) {
rewrite ^/(.*)$ http://www.freeoa.net/$1 permanent;
}
...
}
第二种方法:
server {
server_name freeoa.net;
rewrite ^/(.*) http://www.freeoa.net/$1 permanent;
}
测试了第一种方法ok,这两种方法中,permanent是关键,详细说明见nginx重定向规则说明。
last – 基本上都用这个Flag
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301
重启之后测试一下是否设定成功。
hto@netapp:~$ curl --head freeoa.net
会输出:
HTTP/1.1 301 Moved Permanently
Server: nginx/0.7.65
Date: Fri, 03 Sep 2014 03:00:11 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: http://www.freeoa.net/
nginx做反向代理时出现302错误
现象描述:nginx在使用非80端口做反向代理时,浏览器访问发现返回302错误
出错原因:proxy.conf文件中定义的proxy_set_header Host $host;
意思是nginx接收到浏览器请求后修改请求头中的host信息,然后再把请求转发给后端真实服务节点,服务节点响应后把返回信息传送给nginx,而由于nginx是使用的非80端口做代理,后端服务节点却依然以为nginx是80端口,所以响应信息没有正确的返回给nginx的非80端口。
解决办法:修改为proxy_set_header Host $host:$server_port;即可,这样就把请求头中的host修改为nginx的非80端口了,后端服务节点就知道响应应该返回的正确nginx代理端口
Nginx对不同ip来源重定向不同的页面
使用allow,deny指令只能很简单的限制访问来源,不能实现较为精细的控制。建议使用下面的方法:
1、使用正则匹配来源地址
if ($remote_addr ~ "10\.206\.30\.[7|8]") {
return 301 'http://www.freeoa.net/';
}
将来源ip为10.206.30.7x或8x请求重定向到其它地方。
网段匹配
($remote_addr ~ "10\.206\.[2|3]0")
Ip/Mask 写法在Nginx启动时的报警
nginx: [warn] low address bits of 182.148.201.0/16 are meaningless
错误原因是因为子网划分错误,比如 92.67.220.249/28,每个子网有16个ip所以起始ip一定要是16的倍数这个子网应该写成这样92.67.220.240/28(即网络位),修改完毕后再reload nginx就不会报错了。
2、使用geo模块对多个网段进行匹配
需要安装geo模块,如果编译的话需要使用--with-http_geoip_module选项,系统可能也要安装对应的geo软件开发包。当对多个网段匹配时,上面的写法就不那么友好了,就需要使用geo模块(该模块需要安装),在http段定义
geo $bgt_nmg {
default 0;
218.6.169.95 1;
182.148.201.0/28 1;
}
在server里使用
if ($bgt_foa) {
return 301 'http://www.freeoa.net/';
}
-------------------------------
Good IP (yours): serve page as it is
Bad IP (not yours): redirect to /some-page
location / {
if ($remote_addr != 1.2.3.4) {
rewrite ^ http://www.example.com/some-page;
}
# rest of bla bla
}
location /some-page {
try_files index.html index.php; # or whatever
}
location / {
error_page 403 = @badip
allow 127.0.0.1;
deny all;
}
location @badip {
return 301 $scheme://example.com/some-page;
}
if ( $remote_addr = 1.2.3.4 ) {
proxy_pass http://www.yourwebsite.com/otherpage.htm;
}
在网站建设中需要网页重定向的情况很多:如网页目录结构变动,网页重命名、网页的扩展名改变、网站域名改变等。如果不做重定向,用户的收藏和搜索引擎数据库中的旧地址只能让访客得到一个404错误信息页面,给用户带来不友好的体验。301重定向不仅能使页面实现自动跳转,对于搜索引擎来说,也可能可以传递PR值。
rewrite命令
nginx的rewrite相当于apache的rewrite rule(大多数情况下可以把原有apache的rewrite规则加上引号就可以直接使用),它可以用在server,location和if条件判断块中,命令格式如下:
rewrite 正则表达式 替换目标 flag标记
flag标记可以用以下几种格式:
last – 基本上都用这个Flag。
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301
例如下面这段设定nginx将某个目录下面的文件重定向到另一个目录,$2对应第二个括号(.*)中对应的字符串:
location /download/ {
rewrite ^(/download/.*)/m/(.*)\..*$ $1/nginx-rewrite/$2.gz break;
}
nginx重定向的if条件判断
在server和location两种情况下可以使用nginx的if条件判断,条件可以为以下几种:
正则表达式
匹配判断
~ 为区分大小写匹配; !~为区分大小写不匹配
~* 为不区分大小写匹配;!~为不区分大小写不匹配
例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /nginx-ie/$1 break;
}
文件和目录判断
-f和!-f判断是否存在文件
-d和!-d判断是否存在目录
-e和!-e判断是否存在文件或目录
-x和!-x判断文件是否可执行
例如下面设定nginx在文件和目录不存在的时候重定向:
if (!-e $request_filename) {
proxy_pass http://127.0.0.1/;
}
return
返回http代码,例如设置nginx防盗链:
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked http://www.freeoa.net/ http://www.google.com/;
if ($invalid_referer) {
return 404;
}
}
set
设置nginx变量
301重定向方法
进行了301重定向,把www.freeoa.net和freeoa.net合并,并把之前的域名也一并合并,有两种实现方法。
第一种方法是判断nginx核心变量host:
server {
server_name www.freeoa.net freeoa.net;
if ($host != 'www.freeoa.net' ) {
rewrite ^/(.*)$ http://www.freeoa.net/$1 permanent;
}
...
}
第二种方法:
server {
server_name freeoa.net;
rewrite ^/(.*) http://www.freeoa.net/$1 permanent;
}
测试了第一种方法ok,这两种方法中,permanent是关键,详细说明见nginx重定向规则说明。
last – 基本上都用这个Flag
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301
重启之后测试一下是否设定成功。
hto@netapp:~$ curl --head freeoa.net
会输出:
HTTP/1.1 301 Moved Permanently
Server: nginx/0.7.65
Date: Fri, 03 Sep 2014 03:00:11 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: http://www.freeoa.net/
nginx做反向代理时出现302错误
现象描述:nginx在使用非80端口做反向代理时,浏览器访问发现返回302错误
出错原因:proxy.conf文件中定义的proxy_set_header Host $host;
意思是nginx接收到浏览器请求后修改请求头中的host信息,然后再把请求转发给后端真实服务节点,服务节点响应后把返回信息传送给nginx,而由于nginx是使用的非80端口做代理,后端服务节点却依然以为nginx是80端口,所以响应信息没有正确的返回给nginx的非80端口。
解决办法:修改为proxy_set_header Host $host:$server_port;即可,这样就把请求头中的host修改为nginx的非80端口了,后端服务节点就知道响应应该返回的正确nginx代理端口
Nginx对不同ip来源重定向不同的页面
使用allow,deny指令只能很简单的限制访问来源,不能实现较为精细的控制。建议使用下面的方法:
1、使用正则匹配来源地址
if ($remote_addr ~ "10\.206\.30\.[7|8]") {
return 301 'http://www.freeoa.net/';
}
将来源ip为10.206.30.7x或8x请求重定向到其它地方。
网段匹配
($remote_addr ~ "10\.206\.[2|3]0")
Ip/Mask 写法在Nginx启动时的报警
nginx: [warn] low address bits of 182.148.201.0/16 are meaningless
错误原因是因为子网划分错误,比如 92.67.220.249/28,每个子网有16个ip所以起始ip一定要是16的倍数这个子网应该写成这样92.67.220.240/28(即网络位),修改完毕后再reload nginx就不会报错了。
2、使用geo模块对多个网段进行匹配
需要安装geo模块,如果编译的话需要使用--with-http_geoip_module选项,系统可能也要安装对应的geo软件开发包。当对多个网段匹配时,上面的写法就不那么友好了,就需要使用geo模块(该模块需要安装),在http段定义
geo $bgt_nmg {
default 0;
218.6.169.95 1;
182.148.201.0/28 1;
}
在server里使用
if ($bgt_foa) {
return 301 'http://www.freeoa.net/';
}
-------------------------------
Good IP (yours): serve page as it is
Bad IP (not yours): redirect to /some-page
location / {
if ($remote_addr != 1.2.3.4) {
rewrite ^ http://www.example.com/some-page;
}
# rest of bla bla
}
location /some-page {
try_files index.html index.php; # or whatever
}
location / {
error_page 403 = @badip
allow 127.0.0.1;
deny all;
}
location @badip {
return 301 $scheme://example.com/some-page;
}
if ( $remote_addr = 1.2.3.4 ) {
proxy_pass http://www.yourwebsite.com/otherpage.htm;
}