nginx Rewrite规则可以让网站的url中达到某种状态时定向/跳转到某个规则,可以实现很多功能。
- url访问跳转,支持开发设计,页面跳转、兼容性支持、展示效果、301重定向等。
- SEO优化
- 维护,流量转发
- 安全,如伪静态
内置的全局变量
| 变量名 | 描述 | 
|---|
| $args | 这个变量等于请求行中的参数,同$query_string | 
| $content_length | 请求头中的Content-length字段 | 
| $content_type | 请求头中的Content-Type字段 | 
| $document_root | 当前请求在root指令中指定的值 | 
| $host | 请求主机头字段,否则为服务器名称 | 
| $http_user_agent | 客户端agent信息 | 
| $http_cookie | 客户端cookie信息 | 
| $limit_rate | 这个变量可以限制连接速率 | 
| $request_method | 客户端请求的动作,通常为GET或POST | 
| $remote_addr | 客户端的IP地址 | 
| $remote_port | 客户端的端口 | 
| $remote_user | 已经经过Auth Basic Module验证的用户名 | 
| $request_filename | 当前请求的文件路径,由root或alias指令与URI请求生成 | 
| $scheme | HTTP方法(如http,https) | 
| $server_protocol | 请求使用的协议,通常是HTTP/1.0或HTTP/1.1 | 
| $server_addr | 服务器地址,在完成一次系统调用后可以确定这个值 | 
| $server_name | 服务器名称 | 
| $server_port | 请求到达服务器的端口号 | 
| $request_uri | 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz” | 
| $uri | 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html” | 
| $document_uri | 与$uri相同 | 
1.rewrite模块
rewrite配置项属于ngx_http_rewrite_module模块传送门
rewrite
Syntax:	rewrite regex replacement [flag];  #匹配规则 定向路径 标志参数
Default: —
Context: server, location, if
  
| flag选项 | 描述 | 
|---|
| break | 匹配到之后会在替换后的目录下面去查找 | 
| last | 匹配到之后会在替换后重新用新地址发起请求 | 
| redirect | 返回带有302代码的临时重定向;如果替换字符串不以“http://”,“https://”或“$scheme” | 
| permanent | 返回301代码的永久重定向 | 
break
停止处理当前的ngx_http_rewrite_module指令集。
Syntax:	break;
Default: —
Context: server, location, if
if
如果为true,则执行在大括号内指定的此模块指令,并在if指令内为该请求分配配置
Syntax:	if (condition) { ... }
Default: —
Context: server, location
条件可以是以下任何一种:
- 如果变量的值为空字符串或“0”,则为false;
- 使用=和`!=运算符比较变量和字符串;
- 使用~(对于区分大小写的匹配)和~*(对于不区分大小写的匹配)运算符,将变量与正则表达式进行匹配。正则表达式可以包含可供以后在$1 .. $9变量中重用的捕获。负操作符!~和!~*也可用。如果正则表达式包含}或;字符,则整个表达式应包含在单引号或双引号中。
- 使用-f和!-f运算符检查文件是否存在
- 使用-d和!-d运算符检查目录是否存在
- 使用-e和!-e运算符检查文件,目录或符号链接是否存在
- 使用-x和!-x运算符检查可执行文件。
return
该指令用于结束规则的执行并返回状态码给客户端。
Syntax:	return code [text];
	return code URL;
	return URL;
Default: —
Context: server, location, if
set
Syntax:	set $variable value;
Default: —
Context: server, location, if
2.调试rewrite是否正确
nginx中要检测rewrite是否正确,就需要开启rewrite_log才能排错,rewrite_log会打印错误。检测完后,建议将rewrite_log关闭。
rewrite_log
Syntax:	rewrite_log on | off;
Default: rewrite_log off;
Context: http, server, location, if
示例:
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;
3.break和last区别
rewrite里面flag中break和last是什么区别?请看下面的例子
root /opt/app/code; 
location ~ ^/break {
	rewrite ^/break /test/ break;
} 
location ~ ^/last {
	 rewrite ^/last /test/ last;
}    
location /test/ {
   default_type application/json;
   return 200 '{"status":"success"}';
}
break是停止处理当前的ngx_http_rewrite_module指令集,就是说不会在向下匹配新的location,last停止处理当前的ngx_http_rewrite_module指令集并开始搜索与更改的URI匹配的新位置;
假设我们在页面上访问的url是http://walidream.com/break,根据上面的nginx规则,肯定会匹配到第一个,匹配到第一个之后,根据rewrite正则,url由原来的/break变为/test/但是在root/opt/code/目录 下,没有找到/test/目录下面的内容,所以nginx会返回404错误码。
如果将http://walidream.com/break换成http://walidream.com/last,根据上面的nginx规则,会匹配到第二个location,根据location里面rewrite正则,url由原来的/last变为/test/,但是会重新 匹配loction中,可以简单理解就是将替换后urlhttp://walidream.com/test重新发起一次请求。这个时候会匹配到第三个loaction,根据location里的rewrite正则,会反会200码,并且会返回json内容’{“status”:”success”}’
4.redirect和permanent区别
rewrite里面flag中redirect(临时重定向)和permanent(永久重定向)是什么区别?请看下面的例子
location ~ ^/imooc { 
	rewrite ^/imooc http://www.imooc.com/ redirect;
} 
location ~ ^/wali {
	rewrite ^/wali http://www.imooc.com/ permanent;
}
redirect会返回带有302代码的临时重定向,permanent会返回带有301代码的永久重定向。
假设我们在页面上访问url是http://walidream.com/imooc,根据nginx匹配规则会匹配到第一个location,会重写url,返回一个带有302状态代码,重写后的url是http://www.imooc.com,浏览器会重定向到这个网址, 当我们再次访问http://walidream.com/imooc,nginx还是会先匹配在替换然后重定向。
如果在页面上输入http://walidream.com/wali,根据nginx匹配规则会匹配到第二个location,会重写url,返回一个带有301状态码,重写后的url是http://www.imooc.com,浏览器会重新定向到这个网址, 当我们再次访问http://walidream.com/wali,这个时候浏览器根本不会在经过nginx,而是直接有浏览器重定向到这个网址。
5.rewrite优先级
我们知道rewrite的执行环境是server,location,if。那就有一个问题,当这三个执行环境中都存在rewrite规则,那么执行优先级是什么。
server > location > if
6.利用变量或者return调试
不知道大家写了这么长时间的nginx有没有感觉nginx很难调试,调试一个错误要很长时间。比如上面rewrite 这个就没办法检测自己规则是否在的正确,没有输出,所以要验证rewrite正则是否正确,就要打开 rewrite_log日志,如果匹配错了,日志会记录错误信息。
向一般的检测语法,我们可以利用变量return 返回。
location ~ ^/wali {
	default_type application/json;
	return 200 '{"status":"success"}';
}
location ~ ^/yagm {
	default_type application/json;
	return 200 '{"status":"error"}';
}
这样有时候在调试时会让我们变得稍微方便一点,还有nginx扩展模块如echo就能直接输出内容或者打印内部变量。我们调试起来就更方便了,下面小菜抽一点时间,来讲讲如何安装echo模块。nginx echo传送门