rewrite支持使用 if,set,正则,文件和目录判断
正则表达式匹配:
符号 说明
= 等值的比较
~ 与指定正则表达式模式匹配,区分字符大小写
~* 与指定正则表达式模式匹配,不区分字符大小写
!~ 与指定正则表达式模式不匹配,区分字符大小写
!~* 与指定正则表达式模式不匹配,不区分字符大小写
文件及目录匹配:
符号 说明
-f ,!-f 判断指定路径的文件是否存在
-d, !-d 判断指定路径的目录是否存在
-e, !-e 判断指定路径的文件或目录是否存在
-x, !-x 判断指定路径的文件是否存在且可执行
-r,!-r 判断指定路径的文件是否存在且可读
-w,!-w 判断指定路径的文件是否存在且可写
例子:
1. 判断一个url请求中是否含有敏感字符,包含敏感字符则拒绝请求
location /{
#获取url完整请求
set $URL $scheme://$http_host$request_uri;
#根据获取的URL匹配一些限制字符,满足条件拒绝访
#这里以www字符为例,可自行修改
if ($URL ~ "fuck"){
echo "请求带有敏感字符'fuck',拒绝访问!";
#重定向到首页
#rewrite ^/(.*) http://www.home.com/ permanent;
}
echo "正常访问,url=" $URL;
}
2. 去除 /apis 路径
将 /apis/user/1 重写为 /user/1
location /apis {
proxy_pass http://127.0.0.1:8000/;
proxy_pass_request_headers on;
# 重写URL 去除apis
rewrite "^/apis/(.*)$" /$1 break;
}
3. 修改url路径,保持用户习惯
将imgs重写到images
location /imgs {
rewrite ^/imgs/(.*\.jpg)$ /images/$1 break;
}
4. 浏览器分离
// IE和chrome分别访问不同的url
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
5. 常见各种路径跳转
server {
# 访问 /last.html 的时候,页面内容重写到 /index.html 中,并继续后面的匹配,浏览器地址栏URL地址不变
rewrite /last.html /index.html last;
# 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配,浏览器地址栏URL地址不变;
rewrite /break.html /index.html break;
# 访问 /redirect.html 的时候,页面直接302定向到 /index.html中,浏览器地址URL跳为index.html
rewrite /redirect.html /index.html redirect;
# 访问 /permanent.html 的时候,页面直接301定向到 /index.html中,浏览器地址URL跳为index.html
rewrite /permanent.html /index.html permanent;
# 把 /html/*.html => /post/*.html ,301定向
rewrite ^/html/(.+?).html$ /post/$1.html permanent;
# 把当前域名的请求,跳转到新域名上,域名变化但路径不变
rewrite ^/(.*) http://www.jd.com/$1 permanent;
}
6. 常见path参数转query_string
server {
# 把 /search/key => /search.html?keyword=key
rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
# 对/images/bla_500x400.jpg文件请求,重写到/resizer/bla.jpg?width=500&height=400地址,并会继续尝试匹配location。
rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;
}
7. 禁止访问
# 禁止指定IP访问
location / {
if ($remote_addr = 192.168.1.253) {
return 403;
}
}
# 禁止多个目录
location ~ ^/(cron|templates)/ {
deny all; break;
}
8. 隐藏真实目录
server {
root /var/www/html;
# 用 /html_test 来掩饰 html
location / {
# 使用break拿一旦匹配成功则忽略后续location
rewrite /html_test /html break;
}
# 访问真实地址直接报没权限
location /html {
return 403;
}
}
9. 文件名和参数重写
location = /index.html {
# 修改默认值为
set $name test;
# 如果参数中有 name=xx 则使用该值
if ($args ~* name=(\w+?)(&|$)) {
set $name $1;
}
# permanent 301重定向
rewrite ^ /$name.html permanent;
}
10 域名拦截
# 拦截百度
if ($http_referer ~ 'baidu.com')
{
# return 404;
return 200 "<html><script>window.location.href='//$host$request_uri';</script></html>";
}
# 如果host是www.360buy.com,即非jd.com,则301到www.jd.com中
if ( $host != "www.jd.com" ){
rewrite ^/(.*)$ https://www.jd.com/$1 permanent;
}
11. 方法,文件,cookie,速率等拦截
# 如果文件不存在则返回400
if (!-f $request_filename) {
return 400;
}
# 如果请求类型是POST则返回405,return不能返回301,302
if ($request_method = POST) {
return 405;
}
# 如果参数中有 a=1 则301到指定域名
if ($args ~ a=1) {
rewrite ^ http://example.com/ permanent;
}
# 如果请求的文件不存在,则反向代理到localhost 。这里的break也是停止继续rewrite
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
}
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
if ($request_method = POST) {
return 405;
}
if ($slow) {
limit_rate 10k;
}
if ($invalid_referer) {
return 403;
}