Nginx rewrite重写规则

一、关于rewrite

rewrite语法格式:

rewrite regex replacement [flag];

任何rewrite规则的第一部分都是一个正则表达式,正则表达式中使用圆括号定义的部分可以被位置变量引用,位置变量的值取决于在正则表达式中圆括号定义的顺序;
rewrite的第二部分是被重写后的URI,该URI可以包含位置变量引用第一部分圆括号中定义的内容。
像下面的规则:

rewrite ^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$ /data?file=$3.$4 last;
  • 第一组圆括号中,匹配由两个小写字母“a”至“z”组成的字符串,可以被位置变量“$1”引用;
  • 第二组圆括号中,匹配由五个小写字母或数字组成的字符串,可以被位置变量“$2”引用;
  • 第三组圆括号中,匹配可能是文件名前缀的部分,可以被位置变量“$3”引用;
  • 第四组圆括号中,匹配可能是“png”或“jpg”或“gif”为后缀的文件,可以被位置变量“$4”引用。

二、关于flag的说明

  • last:停止处理rewrite模块指令,并查找重写后的URI匹配的location;
  • break:停止处理rewrite模块指令,并从文件系统中查找对应目录,目录不存在将返回404。如果找到对应文件,则返回重定向信息,并返回网页内容;
  • permanent:永久重定向,返回响应状态码301;
  • redirect:临时重定向,返回响应状态码302。

三、常用正则表达式

表达式 说明
. 匹配除换行符以外的其它任意字符
? 前一个字符匹配0次或1次
+ 前一个字符匹配1次或多次
* 前一个字符匹配0次或多次
\d 匹配数字
^ 匹配字符串的开始
$ 匹配字符串的结尾
{n} 前一个字符匹配n次
{n,} 前一个字符匹配n次或更多次
[n] 匹配方括号中的字符

四、rewrite使用实例

4.1、用rewrite隐去文件的真实路径

假如,在“/usr/local/nginx/html/pc/static/”路径下有“index.html”和“index1.html”,使用rewrite进行重写:

server {
    listen 80;
    server_name 192.168.18.132;
    root /usr/local/nginx/html;
    index index.html index.htm;
    rewrite ^(.*) /pc/static/$1 break;
}

因为Nginx的根路径为“/usr/local/nginx/html”,要访问“pc/static”路径下的文件,则需要在浏览器地址栏中写上文件的完整路径,如“http://192.168.18.132/pc/static/index.html”。经过rewrite重写后,只需要在浏览器中直接访问文件即可:

# curl http://192.168.18.132/index.html

例子中的rewrite规则,也可以这样写:“rewrite ^ /pc/static/$request_uri break;”,结果是一样的。

4.2、使用rewrite将请求跳转到指定路径

比如,想在用户访问到不存在的页面时,都将其跳转到主页上,防止出现404等。配置如下:

server {
    listen 80;
    server_name 192.168.18.132;

    location / {
        root /usr/local/nginx/html;
        index index.html index.htm;
        rewrite ^(.*)$ /index.html break;
    }
}

4.3、使用rewrite将不同请求跳转到不同的路径

比如,为不同的设备(如PC、Android手机等)设定了不同的下载页面,希望通过在浏览器地址栏输入带变量的URI时,可以跳转到对应的下载页面:

server {
    listen 80;
    server_name 192.168.18.132;
    root /usr/local/nginx/html;
    index index.html index.htm;

    location /download {
        if ($query_string ~* 'device=(.*?)$') {
            set $dir $1;
            rewrite '^/download.*?$' /data/$dir? permanent;
        }
    }

    location /data {
        try_files $uri $uri/ @default;
    }

    location @default {
        return 200 "Hello World!";
    }
}

分别为pc、ios、android设定了各自的主页,如下:

# tree /usr/local/nginx/html/data/
/usr/local/nginx/html/data/
├── android
│   └── index.html
├── ios
│   └── index.html
└── pc
    ├── index.html

当在浏览器地址栏访问“http://192.168.18.132/download?device=pc”,将会跳转到相应的页面上:

# curl -L -G -d "device=pc" http://192.168.18.132/download

PC

# curl -L -G -d "device=ios" http://192.168.18.132/download

IOS

# curl -L -G -d "device=android" http://192.168.18.132/download

Android

# curl -L -G -d "device=test" http://192.168.18.132/download Hello World!

注意:
1)配置中的set。由于rewrite指令的第二部分使用位置变量引用正则表达式匹配的内容时,位置变量会从rewrite的第一部分去查找,所以需要将if条件中正则表达式匹配到的内容赋值给常规变量,再在rewrite中引用;
2)注意rewrite规则中,第二部分“/data/$dir?”中的“?”,作用是在跳转后的URI中不显示原URI的“?”后的内容。

五、关于return指令

return指令经常与error_page组合来为客户端提供一个自定义的HTML格式页面,或者激活一个不同的模块来完成请求的处理。
return指令可以指示一个状态码,带有一些文本的状态码,或者带有URI的状态码。如果只有一个URI,那么状态码被理解为302。在将文本放在状态码之后时,该文本就变成了响应体。如果使用了URI,那么该URI变成了Location头的值,客户端将会被重定向。
try_files指令将会按照给定的参数顺序查找,第一个匹配的将会使用。当给定的所有文件都不匹配时,可以将请求传递到一个命名location中。
在4.3节的例子中,通过try_files首先查找文件,再查找目录下的文件,最后会传递到命名location:“@default”中,当然也可以是一个普通的location,例如:“/error_page”或者一个自定义的错误页面,如:“/error_page.html”。location中则通过return指令,返回带文本的响应状态码,用来在所有匹配失败时给出某些信息。
需要注意的是,命名location不能嵌套在其它location中,只能在server {}配置段中使用。
例如,通过try_files和return给出一个error_page:

location / {
    try_files $uri $uri/ /error_page;
}
location /error_page {
    return 404 "Page Not Found!"
}

或者返回一个自定义的HTML页面:

location / {
    try_files $uri $uri/ /404.html;
}

或者将请求转发到其它地址:

location / {
    try_files $uri $uri/ @defaultweb;
}
location @defaultweb {
    return 301 $scheme://www.example.com;
}

或者在命名location中使用反向代理:

location / {
    try_files $uri $uri/ @defaultweb;
}
location @defaultweb {
    proxy_pass http://webserver;
}

六、HTTP强制跳转HTTPS

server {
    listen 80;
    server_name www.example.com;
    rewrite ^(.*)$ https://$host$1 permanent;
}

你可能感兴趣的:(Nginx实践,nginx)