手记

nginx rewrite规则(23)

获取全套nginx教程,请访问瓦力博客

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模块传送门{:target="_blank"}

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中breaklast是什么区别?请看下面的例子

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传送门{:target="_blank"}

0人推荐
随时随地看视频
慕课网APP