- _nosay
Nginx服务器的Rewrite功能(二)
2017-12-09 13:28:59
rewrite指令
该指令通过与此同时表达式的使用来改变URI.可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理.
**提示** *URI与URL的敬贺和联系* URL(Universal Resource Identifier,通用资源标识符),用于对网络中的各种资源进行标识,由存放资源的主机名,片段标志符和相对 URI三部分组成.存放资源的主机名一般由传输协议(Scheme),主机和资源路径三部分组成;片段标志符指向资源内容的具体元素;相对URI表示资源在主机上的相对路径.一般的格式为:Scheme:\[//][用户名[":密码"]@]主机名[:端品号]\[/资源路径]. 该指令可以在server块或者location块中配置,其语法结构为:
rewrite regex replacement[flag];
regex,用于匹配URI的正则表达式.使用括号"()"标记要截取的内容
注意
rewrite接收到的URL不包含host地址.因此,regex不可能匹配到URI的host地址.我们看下面的例子
rewrite myweb.com http://newweb.com/permanent;
现在我们希望上面的rewrite指令重写http://myweb.com/source 是办不到的,因为rewrite指令接收到的URI是"/source",不包含"myweb.com"
另外,请求URL中的请求指令也是不包含在rewrite指令接收到的URL内容中的.比如:
http://myweb.com/source?agr1=value1&agr2=value2
rewrite指令接收到的URI为"/source",不包含"?agr1=value1&agr2=value2".
- replacement,匹配成功后用于替换 URI中被截取的字符串.默认情况下,如果该字符串是由"http://" 或者 "https://" 开头的,则不会继续向下对URI进行其他处理,而直接将重写后的URI返回给客户端.
提示
刚才学习regex变量时我们提到 ,rewrite模块接收到的URI不包含请求URL中的请求指令,但是如果我们希望将这些指令传给重写后的URI,该怎么做呢?我们可以使用Nginx全局变量$request_uri,比如 :
rewrite myweb.com http://example.com$request_uri? permantent;
注意
在$request_uri变量后要添加问号"?".replacement变量中支持Nginx全局变量的使用,常用的还有$uri和$args等.
- flag,用来设置rewrite对URI的处理行为,可以为以下标志中的一个:
- last,终止继续在本location块中处理接收到的URI,并将此处重写的URI作为一个新的URI,使用各location块进行处理.该标志将重写后的URI重新在server块中执行,为重写后的URI提供了转入到其他location块的机会.我们通过一个例子来加深理解.
location /{
rewrite ^(/myweb/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/myweb/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
}
- 如果某URI在第2行被匹配成功并处理,NGINX服务器不会继续使用第3行的配置匹配和处理新的URI,而是让所有的location块重新匹配和处理新的URI.
- break,将此处重写的URI作为一个新的URI,在本块中继续进行处理.该标志将重写后的地址在当前的location块中执行,不会将新的URI转向到其它的location块.看下面的例子:
location /myweb/ {
rewrite ^(/myweb/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/myweb/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
}
- 如果某URI在第2行被匹配成功并处理,NGINX服务器将新的URI继续在该location块中使用第3行进行匹配和处理.新的URI既给是在同一个location块中
- redirect,将重写后的URI返回给客户端,状态代码为302,指明是临时重定向URI,主要用在replacement变量不是以"http://" 或者 "https://" 开头的情况.
- permanent,将重写后的URI返回给客户端,状态代码为301,指明是永久重定向URI
在使用flag指令时,一定要注意各个标志之间的配合.我们再来回顾刚才学习break标志时的例子,对比last标志里的例子,如果我们将第二个例子中的break标志换成last标志,会发生什么情况呢?
细心的读者可能 已经发现,在第二个例子中,location块的urk指令是"/myweb/",而重写后的URI仍然包含"/myweb/"的,如果使用last标志,重写后的URI还可能会被该location块匹配到,这样就是无限循环.Nginx服务器遇到这样的情况,会尝试10次循环之后返回错误状态代码 500.
rewrite_log指令
该指令配置是否开启URI重写日志的输出功能,其语法结构为:
rewrite_log on | off
默认情况为off.如果配置为开户(on),URL重写的相关日志将以notice级别输出到error_log指令的配置的日志文件中.
set指令
该指令设置一个新的变量,其语法结构为:
set variable value
- variable,为变量的名称.注意要用符号"$"作为变量的第一个字符,且变量不能与Nginx服务器预设的全局变量同名.
- value,为变量的值,可以是字符串,其他变量或变量的组合等.
uninitialized_variable_warn指令
该指令用于配置使用未初始化的变量时,是否记录警告日志,其语法结构为:
uninitialized_variable_warn on | off
默认设置为开启(on)状态
Rewrite常用全局变量
在下面的表中,笔者列出了一些在Rewrite功能配置过程中可能会使用到的NGINX全局变量,以备以后的查询
变量 | 查询 |
---|---|
$args | 变量中存放了请求URL中的请求指令.比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的"arg1=value1&arg2=value2" |
$content_length | 变量中存放了请求头中的Content-length字段 |
$content_type | 变量中存放了请求头中的Content-type字段 |
$document_root | 变量中存放了针对当前请求的根路径 |
$document_ui | 变量中存放了请求中的当前URI,并且不包括请求指令,比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的"/server/source" |
$host | 变量中存放了请求中URL中的主机部分字段,比如http://www.myweb.name/server 中的"www.myweb.name". 如果请求中的主机部分字体不可用或者为空,则存放Nginx配置中该server块中的server_name指令的配置值 |
$http_user_agent | 变量中存放客户端的代理信息 |
$http_cookie | 变量中存放客户端的cookie信息 |
$limit_rate | 变量中存放Nginx服务器对网络连接速率的限制,也就是Nginx配置中limit_rate指令的配置值 |
$remote_addr | 变量中存放了客户端的地址 |
$remote_port | 变量中存放了客户端与服务器建立连接的端口号 |
$remote_user | 变量中存放了客户端的用户名 |
$request_body_file | 变量中存放了发给后端服务器的本地文件资源的名称 |
$request_method | 变量中存放了客户端的请求方式 ,如"GET","POST"等 |
$request_filename | 变量中存放了当前请求的资源文件的路径名 |
$request_uri | 变量中存放了当前请求的URI,并且带请求指令 |
$query_string | 与变量$args含义相同 |
$scheme | 变量中存放了客户端请求使用的协议,比如"http","https"和"ftp"等 |
$server_protocol | 变量中存放了客户端请求协议的版本,比如"HTTP/1.0","HTTP/1.1" |
$server_addr | 变量中存放了服务器的地址 |
$server_name | 变量中存放了客户端请求到达的服务器的名称 |
$server_port | 变量中存放了客户端请求到达的服务器的端口号 |
$uri | 与变量$document_uri含义相同 |
rewrite的使用
ngx_http_rewrite_module是Nginx服务器的重要模块之一,它一方面实现了URL的重写功能 ,另一方面为Nginx服务器提供反向代理服务提供了支持,同时,我们可以利用URL重写功能 完成一些Rewrite功能的其他用法,供大家学习和在实际应用中参考.
域名跳转
通过Rewrite功能可以实现一级域名跳转,也可以实现多级域名跳转.在server块中配置Rewrite功能即可.笔者准备了几个例子供大家参考:
#例1
server
{
listen 80;
server_name jump.myweb.name;
rewrite ^/ http://www.myweb.info/;
...
}
#例2
server{
listen 80;
server_name jump.myweb.name jump.myweb.info;
if($host ~ myweb\.info) #注意正则表达示中对点号"."要用'\'进行转义
{
rewrite ^(.*) http://jump.myweb.name$1 permanent; #多域名跳转
}
}
#例3
server{
listen 80;
server_name jump1.myweb.name jump2.myweb.name;
if($http_host ~* ^(.*)\.myweb\.name$)
{
rewrite ^(.*) http://jump.myweb.name$1; #三级域名跳转
}
}
在上面的例子中展示了通过Rewrite功能完成域名跳转的相关配置.
在例1中,客户端访问 http://jump.myweb.name时, URL将被Nginx服务器重写为http://jump.myweb.info; 客户得到的数据其实是由http://jump.myweb.info 响应的.在例2中,客户端访问 http://jump.myweb.info/reqsource时, URL将被Nginx服务器重写为http://jump.myweb.name/reqsource ,客户端得到的数据实际上是由http://jump.myweb.name 响应的.在例3中,客户端访问http://jump1.myweb.name/reqsource 或者http://jump2.myweb.name/reqsource, URL都将被 Nginx服务器重写为http://jump.myweb.name/reqsource, 实现了三级域名的跳转.