Nginx — Rewrite

Rewrite 功能主要就是实现 URL 的重写, Nginx 的 Rewrite 规则采用 PCRE (Perl Compatible Regular Expressions) .Perl 兼容正则表达式的语法进行规则匹配,所以如果要用 Nginx 的 Rewrite 功能,必须在编译之前先安装 PCRE 库。

通过 Rewrite 可以实现规范的 URL, 根据变量来做 URL 转向及选择配置。如,MVC 框架的程序只有一个入口,可以通过 Rewrite 来实现。一些动态URL要伪装成静态HTML便于搜索引擎抓取。一些目录,域名的旧URL通过 rewrite 转到新的上面。
Nginx Rewrite 规则相关指令有:if, rewrite, set, return, break .如:
if(!-f $request_filename){
rewrite ^/img/(.*)$ /site/$host/images/$1 last;
}
 break 
 作用域  server, location, if
 描述  完成当前的规则,不再处理 rewrite 指令
 示例 if($slow){
limit_rate 10k;
break;
}

 

 if
 作用域       server, location
 描述  检查条件是否符合.符合则执行大括号内语句.
不支持嵌套,也不支持多个条件
可作为条件的信息有:
1.变量名.
2.可以用 =, != 进行比较
3.正则表达式匹配可用 ~*(不区分大小写) 和 ~(区分大小写) 匹配
4.!~ , !~* 和上面的相反
5.-f: 文件存在; !-f: 文件不存在
6.-d: 目录存在; !-d: 目录不存在
7.-e: 文件或目录存在; !-e: 文件或目录不存在
8.-x: 文件可执行; !-x: 文件不可执行
9. 正则表达式 () 中的值在后面可通过 $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(!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
}

if($slow){
limit_rate 10k;
}

if($invalid_referer){
return 403;
}

if($args ^~ post=140){
rewrite ^ http://example.com/parm
}

 return
 作用域      server, location, if
 描述  结束规则的执行并返回HTTP状态码给客户端。状态码可以是:
204, 400, 402–406, 408, 410, 411, 413, 416, 500-504
状态码具体的含义查看:
http://blog.sina.com.cn/s/blog_5f54f0be0100kj0f.html
 示例 location ~ .*\(sh|bash)?$ {
return 403;
}
 rewrite
 作用域                                   server, location, if
 描述  根据表达式来重定向 URI, 或者修改字符串。指令按顺序执行。
指令只对相对路径有效,如果想配对主机名,要用其它语句来定位范 围。
rewrite 的最后有一项 flag 标记。值可能是:
1.last, 表示完成当前 rewrite,继续后面的配置
2.break, 本条规则匹配完成后终止匹配,后面的规则无效
3.redirect, 返回 302 临时重定向
4.permanent, 返回 301 永久重定向

last 和 break 用来实现 URI 重写,浏览器地址栏的 URL 不会变,还是用户输入的内容.
redirect 和 permanent 用来实现 URL 跳转,浏览器地址栏显示跳转后的地址
last 和 break 功能类似.但使用 alias 时必须用 last, 使用 proxy_pass 时要使用 break. last 标记在本条 rewrite 规则执行完毕后对其所在的 server 重新发起请求, 这次请求的地址就是该规则 rewrite 后的.

如下面的示例.必须用 break, 用 last 会导致死循环:

location /cms/{
proxy_pass http://test.somesite.com;
rewrite “^/cms/(.*)\.html$” /cms/index.html break;
}

如果请求的URL上有参数,如 /app/test.php?id=5 默认情况下,参数会被自动附加到rewrite 后的地址上.所以这种情况我们要在替换串后加上 ? 来解决:

rewrite ^/users/(.*)$ /show?user=$1? last;
示例:
rewrite ^/test(.*)$ http://www.abc.com/home permanent;
当访问 http://www.abc.com/test?id=5 时,浏览器上地址被 rewrite 成:
http://www.abc.com/home?id=5

加上问号:
rewrite ^/test(.*)$ http://www.abc.com/home? permanent;
地址被 rewrite 成:
http://www.abc.com/home

 示例 location /download/ {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}
 set
 作用域       server, location, if
 描述  定义一个变量,给变量赋值.变量的值可以是文本,变量,及文本变量的联合
 示例 set $varname ‘hello’;

 

rewrite 可以用到的全局变量:
在 if, location, rewrite 指令中,可以使用以下全局变量;
$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
案例:
1.如果文件或目录不存在,重定向到 404 页面
if( !-e $request_filename){
rewrite ^/(.*)$ /index.php last;
}
2.多级目录转成参数
abc.domain.com/sort/2 => abc.domain.com/index.php?act=sort&name=abc&id=2;
if($host ~*(.*)\.domain\.com){
set $sub_name $1;
rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&name=$sub_name&id=$1 last;
}
/123456/xxxx => /xxxx?id=12345
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
/job-123-456-789.html => /job/123/456/789.html
rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;
3.如果客户端使用IE浏览器,重定向到 /nginx-ie 目录下:
if($http_user_agent ~MSIE){
rewrite ^(.*)$ /nginx-ie/$1 break;
}
4.禁止访问某些目录
location ~ ^/(cron|templates)/{
deny all;
break;
}
禁止访问以 /data 开头的文件:
location ~^/data{
deny all;
}
5.只允许指定站点访问本站
if($host ~* ^(.*?)\.aaa\.com$){
set $var_tz ‘1’;
}
if($host ~* ^192\.168\.1\.(.*?)$){
set $var_tz ‘1’;
}
if($host ~* ^localhost){
set $var_tz ‘1’;
}
if($var_tz !~ ‘1’){
rewrite ^/(.*)$ http://www.abc.com/ redirect;
}
原文链接:,转发请注明来源!

发表评论