在使用rewrite模块进行uri重写时,得先补充几个知识点
推荐给nginx安装一个Echo Module,能够非常方便的将我们的请求产生的变量打印出来,nginx选用nginx/1.11.10版本最好,再高一点的版本编译Echo模块会报错。nginx编译成功后添加如下配置。
server {
root /usr/local/nginx/html/;
listen 80;
server_name test.com;
access_log logs/test.com.access.log main;
error_log logs/test.error.log;
location /path/ {
echo "args:" $args;
echo "query_string:" $query_string;
echo "uri:" $uri;
echo "host:" $host;
echo "request_filename:" $request_filename;
echo "request_uri:" $request_uri;
}
}
curl http://test.com/path/file.php?a=1&b=2
args: a=1&b=2
query_string: a=1&b=2
uri: /path/file.php
host: test.com
request_filename: /usr/local/nginx/html/path/file.php
request_uri: /path/file.php?a=1&b=2
语法: rewrite regex replacement [flag]
1,第一个注意的地方就是 regex正则表达是的匹配对象是上文的$uri变量,即不带host和参数的。
rewrite /index.html\?(a=1) index.php?$1 last;
curl test.com/index.html?a=1 是匹配不到不会跳转的
2,默认的情况下请求的参数会跟在replacement的后面,如果重定向后的地址想省略原始请求参数在替换的replacement 后面加上?即可
#请求 test.com/post-21.html?a=1&b=2 会被重定向为 test.com/post.php?page=21&a=1&b=2
rewrite /post-(\d+).html /post.php?page=&1 permanent;
#如果想去掉重定向后的a=1&b=2参数,在replacement加上?
rewrite /post-(\d+).html /post.php?page=&1? permanent;
3,flag:确定重定向的动作
last:停止下面的执行下面的ngx_http_rewrite_module 指令集(包括rewrite,if,return,set这些指令),并开始用重写后新的uri去匹配location。
break:停止下面的执行下面的ngx_http_rewrite_module 指令集。
redirect:服务器发起302临时重定向请求重写的地址
permanent:服务器发起301永久重定向请求重写的地址
last 和 break 当出现在location 之外时,两者的作用是一致的没有任何差异。当出现在location 内部时,两者就存在了差异。
last: 使用了last 指令,rewrite 后会跳出location 作用域,重新开始再走一次刚刚的行为
break: 使用了break 指令,rewrite后不会跳出location 作用域。它的生命也在这个location中终结。
非ngx_http_rewrite_module 任然可以执行,比如proxy_pass ,fastcgi_pass
对用户使用浏览器访问的url来说,last,break都不会改变地址栏的地址。并且不执行后续的rewrite指令,但是last会开始用重写后新的uri去匹配location,如何理解?下面这个例子可以帮助理解。
rewrite /test/.* /index.html break;
location /test/ {
return 508;
}
location /break/ {
rewrite ^/break/(.*) /test/$1 break;
return 402;
}
location /last/ {
rewrite ^/last/(.*) /test/$1 last;
return 403;
}
请求: http://test.com/break/*
返回:404
请求: http://test.com/last/*
返回:508
请求: http://test.com/test/*
返回:200 (返回index.html)
原因:根据上述内容,break与last都停止处理后续rewrite指令集,不同之处在与last会重新发起新的请求,而break不会。当请求break时,如匹配内容存在的话,可以直接请求成功,返回200;而如果请求内容不存在,则返回404。当请求为last的时候,会对重写的新uri重新发起请求,只是重新查找location匹配,如上例则返回508。
4,location与rewrite一些想法
4.1 $uri 与 $request_filename在last,break改变uri后重新查找匹配是变化,但是$request_uri不会变。接着
上例,在请求: http://test.com/last/* 变成新的uri后重新查找时:
uri: /test/*
request_filename: /usr/local/nginx/html/test/*
request_uri: /last/* (不变)
4.2 location 匹配的是$uri,但是rewrite匹配的是request_uri
4.3 rewrite 匹配的优先级高于location