ngx_http_rewrite_module模块

Nginx服务器利⽤ngx_http_rewrite_module 将用户请求的URI基于PCRE regex所描述的模式进行检查,而后完成重定向替换,模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regularexpression),
因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之⼀,⽤于实现URL的重写,URL的重写是⾮常有⽤的功能,⽐如它可以在我们改变⽹站结构之后,不需要客⼾端修改原来的书签,
也⽆需其他⽹站修改我们的链接,就可以设置为访问,另外还可以在⼀定程度上提⾼⽹站的安全性。
 

常用正则表达式:
字符     描述
\      将后面接着的字符标记为一个特殊字符或者一个原义字符或一个向后引用
^      匹配输入字符串的起始位置
$      匹配输入字符串的结束位置
*      匹配前面的字符零次或者多次
+      匹配前面字符串一次或者多次
?      匹配前面字符串的零次或者一次
.       匹配除“\n”之外的所有单个字符
(pattern)  匹配括号内的pattern

 
1.if (condition) { ... }
1.if (condition) { ... }
条件满足时,执行配置块中的配置指令;server, location 
比较操作符condition:
=:  #比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false。 
!=:  #比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false。 
~:  #表示在匹配过程中区分大小写字符,(可以通过正则表达式匹配),满足匹配条件为真,不满足为假。 
~*:  #表示在匹配过程中不区分大小写字符,(可以通过正则表达式匹配),满足匹配条件为真,不满足为假。
!~: #为区分大小写字符且匹配结果不匹配,不满足为真,满足为假。  
!~*: #为不区分大小字符且匹配结果不匹配,满足为假,不满足为真。 

-f 和 ! -f: #判断请求的文件件是否存在和是否不存在 
-d 和 ! -d: #判断请求的目录是否存在和是否不存在。 
-x 和 ! -x: #判断文件件是否可执行和是否不可执行。 
-e 和 ! -e: #判断请求的文件件或目录是否存在和是否不存在(包括文件,目录,软链接)。


注意: if (condition) { ... } 语句中,如果$变量的值为空字符串或是以0开头的任意字符串,则 if 指令认为该条件为false,其它条件为true
示例: http跳转到https
server {
        listen       80;
        listen       443 ssl;
        server_name  rewrite.zjol.com.cn;
        ssl_certificate /usr/local/nginx/ssl/zjol2022.pem;
        ssl_certificate_key /usr/local/nginx/ssl/zjol2022.key;
        ssl_session_cache shared:sslcache:20m;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        charset GB2312;
        location /rewrite {
                root /data/nginx/html/;
                index index.html;
                default_type text/html;
                if ( $scheme = https){
                        echo "if-----> $scheme";
                        echo AAAAAAAAA;   #测试这段时,这里会返回结果
                        #return 301 https://www.magedu.net/;
                }

                echo BBBBBBBB;#测试这段时,这里不返回结果,说明if判断后直接返回结果

          #如果下面还有if语句并为真是,会覆盖BBBBB或AAAAAA的结果。
if ( $scheme = http){ echo "if-----> $scheme"; } } location /rewrite1 { if (-f $request_filename) { echo $request_filename; echo "file is exist"; #return 409; } if (!-f $request_filename) { echo $request_filename; echo "file is not exist"; #return 409; } }}

2.return 返回客户端指定的状态码,多条只执行第一条。

return code [text]; #返回客户端指定的状态码和文本说明
return code URL; #返回客户端指定的状态码和URL
return URL; #返回客户端指定的URL
停止处理,并返回给客户端指定的响应码(包括: 204, 400, 402 — 406, 408, 410, 411, 413, 416, 500 — 504),并对 301, 302, 303, 307, 308跳转到URL

使用curl访问跳转到指定URL
location / {   if ( $http_user_agent ~* curl ){     # return     return http://www.abc.com;
  }
}

测试方法: curl -I -A curl http://www.abc.com

location /rewrite2 {
  if ( $scheme = https ){
    #return 666;
    #return 666 "not allow http";
    return 301 http://www.baidu.com;
    #return 500 "service error";
    echo "if-----> $scheme";#echo不执行

  }
}

测试结果

[root@localhost7D ~]# curl -I -A crul https://rewrite.zjol.com.cn/rewrite2/
HTTP/1.1 666
Server: nginx/1.17.1
Date: Sun, 17 Jul 2022 08:30:51 GMT
Content-Length: 0
Connection: keep-alive

[root@localhost7D ~]# curl -I -A crul https://rewrite.zjol.com.cn/rewrite2/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.17.1
Date: Sun, 17 Jul 2022 08:31:38 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.baidu.com

 

禁止访问http
if ($host != "xinpan.zzhz.zjol.com.cn") {
return 403;
}

 

3.rewrite_log on | off;
是否开启重写日志, 发送至error_log(notice level) (记录要修改notice level) 

location /main {
  index index.html;
  default_type text/html;
  set $name magedu;
  echo $name;
  rewrite_log on;
  break;
  set $my_port $server_port; #记录的是my_port错误,由于break退出,后面的变量有错误。
  echo $my_port; }


tail -f /usr/local/nginx/logs/error.log
2022/07/17 17:21:36 [warn] 51626#0: *146 using uninitialized "my_port" variable, client: 192.168.80.1,
server: rewrite.zjol.com.cn, request: "GET /main/ HTTP/1.1", host: "rewrite.zjol.com.cn



 

4.rewrite 指令

通过正则表达式的匹配来改变URI,可以同时存在⼀个或多个指令,按照顺序依次对URI进⾏匹配,rewrite主要是针对⽤⼾请求的URL或者是URI做具体处理,以下是URL和URI的具体介绍:

URI(universal resource identifier):通⽤资源标识符,标识⼀个资源的路径,可以不带协议。
URL(uniform resource location):统⼀资源定位符,是⽤于在Internet中描述资源的字符串,是URI的⼦集,主要包括传输协议(scheme)、主机(IP、端⼝号或者域名)和资源具体地址(⽬录和⽂件名)等三部分,⼀般格式为
scheme://主机名[:端⼝号][/资源路径],如:http://www.a.com:8080/path/file/index.html就是⼀个URL路径,URL必须带访问协议。
每个URL都是⼀个URI,但是URI不都是URL。
例如:
http://example.org:8080/path/to/resource.txt   #URI/URL
ftp://example.org/resource.txt          #URI/URL
/absolute/path/to/resource.txt         #URI

rewrite regex replacement [flag];
将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为replacement指定的新的URI
注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查
隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的标志位用于控制此循环机制
如果replacement是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向301


rewrite flag使⽤介绍
[flag]:
last:   重写完成后停止对当前URI在当前location中后续的其它重写操作,而后对新的URI启动新一轮重写检查;提前重启新一轮循环,不建议在 location中使用。
break:  重写完成后停止对当前URI在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块后的其它配置;结束循环。
redirect:  临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;可使用相对路径,或http://或https://开头,此重定向信息不可缓存,状态码:302
permanent: 重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求,此重定向信息可缓存DNS解析记录(状态码后面有:from disk cache),状态码:301

 

break: 匹配成功后不再向下匹配,也不会跳转到其他的location,即直接结束匹配并给客户端返回结果数据
last: 对某个location的URL匹配成功后会停止当前location的后续rewrite规则,并结束当前location,然后将匹配生成的新URL跳转至其他location继续匹配,直到没有location可匹配后将最后一次location的数据返回给客户端


redirect(临时重定向)、permanent(永久重定向): 跳转型, 跳转型是指有客户端浏览器重新对新地址进行请求
break和last: 代理型,代理型是在WEB服务器内部实现跳转的。

 

4.1 rewrite案例--redirect与permanent:


[root@localhost7B html]# mkdir aaa bbb
[root@localhost7B html]# echo aaa.zjol.com.cn > aaa/index.html
[root@localhost7B html]# echo bbb.zjol.com.cn > bbb/index.html

#要求:因业务需要,将访问源域名 www.magedu.net 的请求永久重定向到www.magedu.com 。 临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存。
server { listen
80; listen 443 ssl; server_name aaa.zjol.com.cn; ssl_certificate /usr/local/nginx/ssl/zjol2022.pem; ssl_certificate_key /usr/local/nginx/ssl/zjol2022.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; charset GB2312; location / { root /data/nginx/html/aaa; index index.html;

          #域名永久重定向,京东早期的域名 www.360buy.com 由于与360公司类似,于是后期永久重定向到了 www.jd.com ,永久重定向会缓存DNS解析记录。
          rewrite / https://bbb.zjol.com.cn permanent;


          #域名临时重定向,告诉浏览器域名不是固定重定向到当前⽬标域名,后期可能随时会更改,因此浏览器不会缓存当 前域名的解析记录,⽽浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最⼤的本质区 别。
          #rewrite / https://bbb.zjol.com.cn redirect;

        }
}

server {
        listen       80;
        listen       443 ssl;
        server_name  bbb.zjol.com.cn;
        ssl_certificate /usr/local/nginx/ssl/zjol2022.pem;
        ssl_certificate_key /usr/local/nginx/ssl/zjol2022.key;
        ssl_session_cache shared:sslcache:20m;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        charset GB2312;
        location / {
                root /data/nginx/html/bbb;
                index index.html;
        }
}
permanentr的测试结果,  注意有些浏览器不会显示from disk cache

 

redirect的测试结果

 

 

4.2 .break指令

⽤于中断当前相同作⽤域(location)中的其他Nginx配置,与该指令处于同⼀作⽤域的Nginx配置中,位于它前⾯的配置⽣效,位于后⾯的指令配置就不再⽣效了,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,
回到上⼀层作⽤域继续向下读取配置,该指令可以在server块和location块以及if块中使⽤,使⽤语法如下:
location /rewrite3 {
  root /data/nginx/html/pc;
  index index.html;
  default_type text/html;
  set $name magedu;
  echo $name;
  break; #结束循环,下面的$my_port不执行;
  set $my_port $server_port; echo $my_port; }
break适⽤于不改变客⼾端访问⽅式,但是要将访问的⽬的URL做单次重写的场景,⽐如有V1/V2两个版本的⽹站前端⻚⾯并存,
旧版本的⽹站数据已经保存到了statics不能丢失,但是要将访问新版本的资源重写到新的静态资源路径到新的⽬录static:
location /statics {
  root /data/nginx;
  index index.html;
  rewrite ^/statics/(.*) /static/$1 break;
}

 4.2 rewrite案例--break:

[root@localhost7B html]# mkdir break test1 test2
[root@localhost7B html]# echo break > break/index.html
[root@localhost7B html]# echo test1 > test1/index.html
[root@localhost7B html]# echo test2 > test2/index.html

server {
  listen 80;
  listen 443 ssl;
  server_name aaa.zjol.com.cn;
  ssl_certificate /usr/local/nginx/ssl/zjol2022.pem;
  ssl_certificate_key /usr/local/nginx/ssl/zjol2022.key;
  ssl_session_cache shared:sslcache:20m;
  ssl_session_timeout 5m;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  charset GB2312;

  location /break {
    #return 666 "break";
    root /data/nginx/html;
    index index.html;
    rewrite ^/break/(.*) /test1/$1 break;
    #break匹配成功后不再向下匹配,也不会跳转到其他的 location,即直接结束匹配并给客⼾端返回结果数据。 $1是取regex部分第一个()里面的内容.
    rewrite ^/test1/(.*) /test2/$1 break;
    #break不会匹配后⾯的rewrite规则也不匹配其他 location
  }
  location = /test1 {
    return 999 "new test1";
    #index index.html;
    #root /data/nginx/html;
  }
  location = /test2 {
    return 666 "new test2";
    #root /data/nginx/html;
    #index index.html;
  }}

 

测试结果

[root@localhost7D ~]# curl aaa.zjol.com.cn/break/index.html  #没有匹配location = /test1和location = /test2
test1
[root@localhost7D ~]# curl aaa.zjol.com.cn/test1
new test1

[root@localhost7D ~]# curl aaa.zjol.com.cn/test2
new test2

 

rewrite案例--last
对某个location的URL匹配成功后会停⽌当前location的后续rewrite规则,并结束当前location,然后将匹配⽣成的新URL跳转⾄其他location继续匹配,直到没有location可匹配后将最后⼀次location的数据返回给客⼾端。
例3: last 和 break
#last适用于要不改变客户端访问方式但是需做多次目的URL重写的场景,场景不是很多。
location /last {
                root /data/nginx/html;
                index index.html;
                rewrite ^/last/(.*) /test3/$1 last; #last会跳转到其他的location继续匹配新的URI
                #arewrite ^/test3/(.*) /test4/$1 last;
         }
        location /test3 {
                #return 999 "new test3";
                index index.html;
                root /data/nginx/html;
                rewrite ^/test3/(.*) /test4/$1 last;
        }
        location /test4 {
                return 666 "new test4";
                #root  /data/nginx/html;
                #index index.html;
        }

 rewrite案例

例:将 http:// 请求跳转到 https://
location / {
if ($scheme = http ) {
rewrite / https://www.magedu.net/ redirect;

#rewrite ^(.*)$ http://land.zzhz.zjol.com.cn/$1 permanent;

#rewrite ^/(.*)$ http://land.zzhz.zjol.com.cn/$1 permanent;

} }


例:要求:当用户访问到公司网站的时输入了一个错误的URL,可以将用户重定向至官网首页
location / {
root /data/nginx/html/pc;
index index.html;
if (!-e $request_filename) {
#return 404 "No exsit";
rewrite (.*) http://www.magedu.net/index.html;} }

 

例 http://www.magedu.com/bj --> http://www.magedu.com/beijing

location /bj {
    rewrite ^/bj/(.*)$  /beijing/$1 last;}
location /beijing {
    rewrite default_type text/html;}

 

posted @ 2022-07-17 17:35  yuanbangchen  阅读(316)  评论(0编辑  收藏  举报