Nginx rewrite指令
2013-03-26 by dongnan
举个栗子
下面的nginx配置文件有两个rewrite配置示例:
cat /etc/nginx/conf.d/default.conf
server
{
server_name test.com www.test.com;
#... 其它配置项省略
# 访问 test.com,301重定向到 www.test.com
if ($host != 'www.test.com') {
rewrite ^(.*)$ http://www.test.com$1 permanent;
}
location / {
# 伪静态
rewrite ^/$ /index.php?_c=index&_a=index last;
rewrite ^/demo/(.*)/(.*)\.html$ /index.php?_c=$1&_a=$2 last;
}
#... 其它配置项省略
}
测试
使用curl命令测试 rewrite 规则:
curl -IL test.com
HTTP/1.1 301 Moved Permanently
Server: nginx
#...省略
Location: http://www.test.com/
HTTP/1.1 200 OK
Server: nginx
#...省略
返回结果中看到curl命令共请求了两次:
- 第1次服务器返回
301状态码test.com被重定向新的Location: http://www.test.com/。 - 第2次访问新的地址是
www.test.com返回200状态码 。
相对路径
需要说明的是rewrite正则表达式部分只对相对路径有效:
- 如果你想匹配主机名(比如
test.com参考上面例子),请与if指令、$host变量配合使用。 - 如果你想匹配参数(比如
id=1参考下面例子),请与if指令、$query_string变量配合使用。
什么是相对路径
以 http://www.test.com/demo?id=1 为例:
- 主机名
www.test.com - 相对路径
/demo - 参数
?id=1
配置文件:
{
#... 其它配置项省略
if ($query_string ~* "id=(.+)$") {
rewrite ^/ http://demo.com/so.php permanent;
}
}
rewrite 指令
- 语法:
rewrite regex replacement flag - 默认值:
none - 使用字段:
server, location, if - 功能: 按照相关的正则表达式或者字符串来重写URI,
rewrite指令按照在配置文件中出现的顺序执行,可以在重写指令后面添加需要的标记。
flag 标记:
last:完成重写指令,之后搜索相应的URI或location。break:完成重写指令,之后停止搜索。redirect:返回302临时重定向,浏览器地址栏会显示跳转后URL地址。permanent:返回301永久重定向,浏览器地址栏会显示跳转后URL地址。
引用张宴老师的一段话:
last与break,用来实现URI重写,浏览器地址栏URL地址不变,但是在服务器端访问的路径已经发生了变化。redirect与permanent,用来实现URL跳转,浏览器地址栏会显示跳转后URL地址。last与break是有区别的,last标记在匹配后继续搜索,而break标记在匹配后则停止搜索。
因此一般在根 location 中(即 location /{..}),
或者直接写在 server 标签中的 rewrite 规则使用last标记,
而在非根 location 中(比如 location /pic/{..})使用break标记。
注意:
- 如果替换的字符串以
http(s)://开头,请求将被301或者302 URL重定向,并且不再执行多余的rewrite指令。 - 正则表达式的一部分可以用圆括号括起来,方便之后按照顺序用
$1-$9来引用,例如上例中的$1与$2引用方式。
if 指令
- 语法:
if (condition) { … } - 默认值:
none - 使用字段:
server, location - 功能: 判断一个条件,如果条件成立则后面的大括号内的指令将执行,相关配置从上级继承。
条件
条件可以是以下任意一个:
变量名称,不成立的值为: ""(空字符串)"或者一些用0开始的字符串。
- 变量比较可以使用
=(表示等于)或者使用!=(表示不等于)运算符。
正则表达式的模式匹配使用符号 ~*或~。
~为区分大小写的匹配。~*不区分大小写的匹配(abc匹配ABC)。!~和!~*意为"不匹配的"。
测试目标 -f/-d/-e/-x:
- 使用
-f和!-f检查一个文件是否存在。 - 使用
-d和!-d检查一个目录是否存在。 - 使用
-e和!-e检查一个文件,目录或者软链接是否存在。 - 使用
-x和!-x检查一个文件是否为可执行文件。