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;
}