Nginx 重写URI

重写URI

我们在使用Nginx的过程中经常碰到需要将客户端访问者的URI进行重写,在“根据浏览器选择主页”部分多少有些认识这种做法,另外我们我们在“map模块的使用”部分也见到和改写过,但是它们都没有rewrite模块强大,因此,在这一部分我们看看rewrite的用法。

使用rewrite模块离不开正则表达式,因此,要想使用rewrite指令,那么就必须在安装Nginx时指定pcre。

使用该模块通过正则表达式(PCRE)就可以改变URI,并且可以重定向和根据变量来选择配置。如果在server级别执行rewrite指令,那么请求将在location确定之前执行。如果在被选择的location中仍有rewrite指令,那么它们同样被执行,如果在这个location中又触发访问到rewrite指令,那么就会再次改变URI。这种被重复周期为10才, 在10次之后仍然找不到具体的URI,那么Nginx将会返回500错误。

配置示例

rewrite ^/(/d+)/(.+)/ /$2?id=$1 last;

rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

if (-d $request_filename){

rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;

}

if ($http_host ~* "^(.*)/.st/.xx/.com$") {

rewrite ^(.*) http://st.yy.com$1;

break;

}

if ($host ~* (.*)\.xx\.com) {

set $sub_name $1;

rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last;

}

if ($http_user_agent ~ MSIE) {

rewrite ^(.*)$ /var/www/ie/$1 break;

}

安装PCRE

下载并安装pcre:

[root@s29 ~]# wget ftp://ftp.csx.cam.ac.uk/pub/software \

> /programming/pcre/pcre-8.13.tar.gz

[root@s29 ~]#tar -zxvf pcre-8.13.tar.gz

[root@s29 ~]#cd pcre-8.13

[root@s29 pcre-8.13]#./configure --prefix=/usr/local/pcre-8.13   \

> --enable-utf8 --enable-unicode-properties

[root@s29 pcre-8.13]#make

[root@s29 pcre-8.13]#make install

需要注意的是,在安装Nginx时:

[root@mail nginx-1.0.2]# ./configure --prefix=/usr/local/nginx-1.0.2-pcre-8.13 \

> --with-pcre=/root/pcre-8.13

……

Configuration summary

+ using PCRE library: /root/pcre-8.13

+ OpenSSL library is not used

+ md5: using system crypto library

+ sha1 library is not used

+ using system zlib library

……

这里的--with-pcre指定的是pcre-8.13的源码,但是在Nginx的安装过程中会查找pcre安装的具体情况:

.....//无法上传省略

指令名称:if

语    法: if (condition) { ... }

默 认 值: none

使用环境: server, location

功    能:用于检测条件是否成立,如果条件被评估为真,那么在大括号“{}”中代码将会被执行,同配置中一致的请求将会被处理。if指令内部的配置会被从上一级继承。需要注意的是,使用if指令要谨慎,尽量考虑是try_files指定。

条件condition部分可以指定下列值:

n  使用= 或 !=操作符比较变量的表达式;

n  变量名称,如果变量名称为false,那么值将会是一个空字符串(""),或者是

任何以"0"开始的字符串

n  使用正则表达式的模式匹配:

u             ~    执行区分大小写匹配;

u             ~*   执行不区分大小写匹配;

u             !~   执行区分大小写不匹配

u             !~*  执行不区分大小写不匹配

n  使用 -f 或者 !-f 操作符检测文件的存在性;

n  使用 -d 或者 !-d 操作符检测目录的存在性;

n  使用 -e 或者 !-e 操作符检测文件、目录或者符号连接的存在性;

n  使用 -x 或者 !-x 检测文件是否可执行。

正则表达式部分可以放在括号内,以便在以后的使用中可以通过变量$1 到 $9来访问。例如:

if ($http_user_agent ~ MSIE) {

rewrite  ^(.*)$  /msie/$1  break;

}

if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) {

set  $id  $1;

}

if ($request_method = POST ) {

return 405;

}

if ($slow) {

limit_rate  10k;

}

if ($invalid_referer) {

return   403;

}

if ($args ~ post=140){

rewrite ^ http://example.com/ permanent;

}

在条件判断中可以使用的一些全局变量:$args、$content_length、$content_type、$document_root、$document_uri、$host、$http_user_agent、$http_cookie、$limit_rate、$request_body_file、$request_method、$remote_addr、$remote_port、$remote_user、$request_filename、$request_uri、$query_string、$scheme、$server_protocol、$server_addr、$server_name、$server_port、$uri。

指令名称:return

功    能: 该指令会结束执行规则,并且会为客户端返回状态码。可使用的代码值:204, 400, 402-406, 408, 410, 411, 413, 416 和 500-504,此外,非标准的代码444将会关闭连接而不会发送任何头

功    能: return code

默 认 值: none

使用环境: server, location, if

指令名称:rewrite

语    法: rewrite regex replacement flag

默 认 值: none

使用环境: server, location, if

功    能:该指令会按照相关的regex正则表达式和replacement替换字符串改变URI,rewrite指令会按照自己在配置文件中出现的顺序执行,这一点要格外注意。

如果replacement替代字符串由http://开始,那么客户端将会被重定向redirect,任何其它后面的rewrite指令都被终结。

标志flag用于结束rewrite指令,它的可取值有:

l         last - 在搜索到相应的URI和location之后完成rewrite指令;

l         break - 完成 rewrite指令处理

l         redirect - 返回302临时重定向,如果replacement替换部分是由http://开始,它将被应用。

l         permanent - 返回30代码永久重定向

注意,如果重定向是相当的,即没有主机部分,那么当使用重定向时,Nginx使用"Host"头的顺序为:如果有匹配server_name指令指定的主机名,那么则使用它;如果没有,那么将会使用第一个server_name设置的值;如果仍然没有,那么本地主机名会被使用。如果想让Nginx总是使用"Host"头,那么可以在server_name指令中使用"*"(但是这么做会有限制)。例如:

rewrite ^(/download/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  last;

rewrite ^(/download/.*)/audio/(.*)\..*$  $1/mp3/$2.ra   last;

return  403;

如果我们将这些指令放置在/download/中,那么有必要将标志"last" 替换为 "break",否则Nginx在经过10 循环后将会返回500错误:

location /download/ {

rewrite ^(/download/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  break;

rewrite ^(/download/.*)/audio/(.*)\..*$  $1/mp3/$2.ra   break;

return  403;

}

如果在replacement替换部分包含参数,那么其余的参数添加在后面,另外,为了避免参数部分再被附加,可以在参数部分最后一个字符后再放置一个”?”。例如:

rewrite  ^/users/(.*)$  /show?user=$1?  last;

注意使用大括号( { 和 } ),由于它们可以同时使用在正则表达式和区段(就是http、server、location、if)控制中,为了避免歧义、冲突,因此在正则表达式中使用大括号( { 和} )那么将它们使用双引号或者单引号来括起。例如:

我们将/photos/123456  重定向该URL到/path/to/photos/12/1234/123456.png

(文/nginx_web)

本文来源:http://blog.itpub.net/27043155/viewspace-734211/


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。