[转帖]Nginx Rewrite重写功能

nginx,rewrite,重写,功能 · 浏览次数 : 0

小编点评

**location** 定义文件中包含以下内容: * **域名匹配**:例如 `location / {}=`匹配所有域名,将请求转发到 `www.accp.com`。 * **客户端 IP匹配**:例如 `location /abc {}`匹配所有以 `abc` 开头的地址,将请求转发到 `mail.accp.com`。 * **参数匹配**:例如 `location /abc {}`匹配所有以 `abc` 开头的地址,并将参数 `100`传递到 `mail.accp.com`。 * **目录下所有文件跳转**:例如 `location ~ /100-(100|200)-\\d+.html$ {}`匹配所有以 `100-100|200-`开头的地址,并将参数 `100`传递到 `mail.accp.com`。 **其他配置**: * **`$rewrite`**变量存储着重写后的结果,例如域名后缀。 * **`location /`**块匹配所有请求,并将请求转发到 `www.accp.com`。 * **`location ~ /100-(100|200)-\\d+.html$ {`**块匹配以 `100-100|200-`开头的地址,并将参数 `100`传递到 `mail.accp.com`。 **总结**: 这配置定义了多个域名匹配、客户端 IP匹配、参数匹配和目录下所有文件跳转请求,并使用 `$rewrite`变量存储重写后的结果。

正文


一、rewrite的概述

1.1、概述

rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。
比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。
rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用,
例如:http://www.test.com/abc/bbs/index.php?a=1&b=2 只对/abc/bbs/index.php重写

URL:就是具体的路径/位置
URI:指的就是一个拥有相同类型/特性的对象集合

location是为了匹配访问路径(URL)
if作为判断分支,并且if分支,仅支持单分支

rewrite:对访问路径进行改写
1、改写路径:nginx服务器上的配置-改写路径
2、改写路径:在后端、其他服务器上-跳转

1.2 跳转场景

1、可以使用户浏览URL的时候,看起来更加规范,合理;例:http://www.baidu.com/index.html

2、为了让用户搜索网页的体验更好,企业会将动态URL地址伪装成静态地址从而提供服务

3、网址换新域名后,会让旧的访问跳到新的域名上

4、服务端某些业务的调整

1.3 跳转实现

1、Nginx:通过ngx_http_rewrite_module 模块支持URL重写、支持if条件判断,但不支持else

2、跳转:从一个 location跳转到另一个location,循环最多可以执行10次,超过后nginx将返回500错误

3、PCRE支持:perl兼容正则表达式的语法规则匹配

4、重写模块 set 指令:创建新的变量并设其值

在这里插入图片描述

1.4 Rewrite实际场景

Nginx跳转需求的实现方式

  1. 使用rewrite进行匹配跳转(防盗链)
  2. 使用if匹配全局变量后跳转(nginx服务本身的全局变量)
  3. 使用location匹配再跳转

rewrite放在 server{},if{},location{}段

location只对域名后边的除去传递参数外的字符串起作用

对域名或参数字符串
使用if全局变量匹配
使用proxy_pass反向代理

二、常用的nginx正则表达式

^ :匹配输入字符串的起始位置
$ :匹配输入字符串的结束位置
* :匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll”
+ :匹配前面的字符一次或多次。如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o”
? :匹配前面的字符零次或一次,例如“do(es)?”能匹配“do”或者“does”,”?”等效于”{0,1}”
. :匹配除“\n”之外的任何单个字符,若要匹配包括“\n”在内的任意字符,请使用诸如“[.\n]”之类的模式
\ :将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如“\n”匹配一个换行符,而“\$”则匹配“$”
\d :    匹配纯数字
{n} :   重复 n 次
{n,} :  重复 n 次或更多次
{n,m} : 重复 n 到 m 次
[] :    定义匹配的字符范围
[c] :   匹配单个字符 c
[a-z] : 匹配 a-z 小写字母的任意一个
[a-zA-Z0-9] :匹配所有大小写字母或数字
() :表达式的开始和结束位置
| : 或运算符

    正则表达式的优势

    1、精确匹配,减少遍历的消耗

    2、节省服务响应的资源消耗

    3、提高用户体验感

    4、提高服务器并发时、处理效率/性能

    三、rewrite命令

    3.1 rewrite的语法格式

    语法格式:rewrite <regex> <replacement> [flag];
    regex :表示正则匹配规则。
    replacement :表示跳转后的内容。
    flag :表示 rewrite 支持的 flag 标记。
    

      3.2 fiag标记说明

      last :本条规则匹配完成后,继续向下匹配新的location URL规则,一般用在 server 和 if 中。

      break :本条规则匹配完成即终止,不再匹配后面的任何规则,一般使用在 location 中。

      redirect :返回302临时重定向,浏览器地址会显示跳转后的URL地址。

      permanent :返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。

      四、location

      从功能看,rewrite 和 location 似乎很像,都能实现跳转,主要区别在于 rewrite 是在同一域名内更改获取资源的路径,而 location 是对一类路径做控制访问或反向代理,还可以 proxy_pass 到其他机器。

      4.1 location大致分为三类

      精准匹配:location = / {…}
      一般匹配:location / {…}
      正则匹配:location ~ / {…}

      4.2 location 常用的匹配规则

      = :进行普通字符精确匹配,也就是完全匹配。
      ^~ :表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其它 location。
      ~ :区分大小写的匹配。
      ~* :不区分大小写的匹配。
      !~ :区分大小写的匹配取非。
      !~* :不区分大小写的匹配取非。

      4.3 location的优先级

      相同类型的表达式,字符串长的会优先匹配

      首先精确匹配 =
      其次前缀匹配 ^~
      其次是按文件中顺序的正则匹配 *
      然后匹配不带任何修饰的前缀匹配
      最后是交给 / 通用匹配

      优先级总结:
      (location = 完整路径) > (location ^~ 路径) > (location ,
      正则顺序) > (location 部分起始路径) > (location /)
      *

      4.4 location示例

      (1)location = / {}
      =为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配
      再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。若 location  /abc,则即匹配/abc 、/abcd/ 同时也匹配 /abc/。
      

      (2)location / {}
      因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
      但若后面是正则表达式会和最长字符串优先匹配(最长匹配)

      (3)location /documents/ {}
      匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
      只有其它 location后面的正则表达式没有匹配到时,才会采用这一条

      (4)location /documents/abc {}
      匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
      只有其它 location后面的正则表达式没有匹配到时,才会采用这一条

      (5)location ^~ /images/ {}
      匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条

      (6)location ~* .(gif|jpg|jpeg)$ {}
      匹配所有以 gif、jpg或jpeg 结尾的请求;然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则

      (7)location /images/abc {}
      最长字符匹配到 /images/abc,优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在

      (8)location ~ /images/abc {}
      匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条

      (9)location /images/abc/1.html {}
      匹配/images/abc/1.html 文件,如果和正则location ~ /images/abc/1.html 相比,正则优先级更高

        五、rewrite实例

        5.1 基于域名的跳转

        现在公司旧域名www.accp.com有业务需求变更,需要使用新域名www.benet.com代替,但是旧域名不能废除,需要跳转到新域名上,而且后面的参数保持不变。

        vim /usr/local/nginx/conf/nginx.conf
        server {
        	listen       80;
        	server_name  www.accp.com;		#域名修改	
        	charset utf-8;
        	access_log  /var/log/nginx/www.accp.com-access.log;		#日志修改
        	location / {
        	#添加域名重定向
                if ($host = 'www.accp.com'){						#$host为rewrite全局变量,代表请求主机头字段或主机名
        			rewrite ^/(.*)$ http://www.benet.com/$1 permanent;	#$1为正则匹配的内容,即“域名/”之后的字符串
                }
                root   html;
                index  index.html index.htm;
            }
        }
        
          mkdir -p /var/log/nginx  #创建日志文件位置
          
          • 1

          在这里插入图片描述
          在这里插入图片描述
          在这里插入图片描述

          在这里插入图片描述

          5.2 基于客户端 IP 访问跳转

          今天公司业务新版本上线,要求所有 IP 访问任何内容都显示一个固定维护页面,只有公司 IP :192.168.154.10 访问正常。

          vim /usr/local/nginx/conf/nginx.conf
           server {
                  listen       80;
                  server_name  www.accp.com;
          
              charset utf-8;
          
              access_log  /var/log/nginx/www.accp.com-access.log;
          
              set $rewrite true;          #设置变量$rewrite,变量值为boole值true
              if ($remote_addr = "192.168.154.11"){   #当客户端IP为192.168.190.52时,将变量值设为false,不进行重写
                  set $rewrite flase;
          
              }
              #除了合法IP,其它都是非法IP,进行重写跳转维护页面
              if ($rewrite = true) {         #当变量值为true时,进行重写
                   rewrite (.+) /weihu.html;     #将域名后边的路径重写成/weihu.html
              }
              location = /weihu.html {           
                root /var/www/abc;       #网页返回/var/www/html/weihu.html的内容
              }
          
              location / {
                  root   html;
                  index  index.html index.htm;
          
              }
          

            在这里插入图片描述
            在这里插入图片描述

            在这里插入图片描述
            在这里插入图片描述

            5.3 基于旧域名跳转到新域名后面加目录

            现在访问的是 http://mail.accp.com/abc/,现在需要将这个域名下面的访问都跳转到http://www.accp.com/mail/abc/

            vim /usr/local/nginx/conf/nginx.conf
            server {
                    listen       80;
                    server_name  mail.accp.com;   #域名修改
            
                #charset koi8-r;
            
                #access_log  logs/host.access.log  main;
            
                location / {
                    root   html;
                    index  index.html index.htm;
                }
            
                location /abc {
                      rewrite (.+) http://www.accp.com/mail$1 permanent;    #这里的$1为位置变量,代表/abc
                }
            

              在这里插入图片描述
              在这里插入图片描述

              mkdir -p /usr/local/nginx/html/mail/abc
              echo 'this is rewrite test web!' > /usr/local/nginx/html/mail/abc/test.html
              

                在这里插入图片描述

                在这里插入图片描述
                在这里插入图片描述

                5.4 基于参数匹配的跳转

                现在访问http://www.accp.com/100-(100|200)-123456.html 跳转到http://www.accp.com页面。

                vim /usr/local/nginx/conf/nginx.conf
                server {
                        listen       80;
                        server_name  www.accp.com;
                
                    #charset koi8-r;
                
                    #access_log  logs/host.access.log  main;
                
                    location / {
                        root   html;
                        index  index.html index.htm;
                    }
                
                    # location /abc {
                    #      rewrite (.+) http://www.accp.com/mail$1 permanent;
                    #}
                
                    location ~ /100-(100|200)-\d+.html$ {
                        rewrite (.+) http://www.accp.com permanent;
                    }
                

                  在这里插入图片描述

                  在这里插入图片描述
                  在这里插入图片描述

                  在这里插入图片描述

                  5.5 基于目录下所有 php 结尾的文件跳转

                  要求访问 http://www.accp.com/bbs/index.php 跳转到首页。

                  location ~* /bbs/.*\.php$ {
                              rewrite (.+) http://www.accp.com permanent;
                          }
                  

                    在这里插入图片描述
                    在这里插入图片描述

                    在这里插入图片描述

                    与[转帖]Nginx Rewrite重写功能相似的内容:

                    [转帖]Nginx Rewrite重写功能

                    目录 一、rewrite的概述1.1、概述1.2 跳转场景1.3 跳转实现1.4 Rewrite实际场景 二、常用的nginx正则表达式三、rewrite命令3.1 rewrite的语法格式3.2 fiag标记说明 四、location4.1 location大致分为三类4.2 location 常

                    [转帖]Nginx中的Rewrite的重定向配置与实践

                    https://www.cnblogs.com/tugenhua0707/p/10798762.html 阅读目录 一:理解地址重写 与 地址转发的含义。 二:理解 Rewrite指令 使用 三:理解if指令 四:理解防盗链及nginx配置 简介:Rewrite是Nginx服务器提供的一个重要的功能

                    [转帖]详解nginx的rewrite应用,Nginx高级之Rewrite规则

                    https://zhuanlan.zhihu.com/p/359801091 Rewrite主要的功能是实现URL重写,Nginx 的 Rewrite 规则采用 PCRE Perl 兼容正则表达式的语法进行规则匹配,如相使用 Nginx 的 Rewrite 功能,在编译 Nginx 前要编译安装 P

                    [转帖]Nginx:地址重写(return和rewrite)

                    https://www.cnblogs.com/testopsfeng/p/15294660.html Nginx的重写指令用于改变客户端的URL请求。主要有return和rewrite。两个指令都有重写URL的能力,但rewrite支持更复杂的功能。 Return指令 在server中返回 301

                    [转帖]Nginx动静分离;资源分离;rewrite重写、跳转、伪静态、规则、日志

                    https://www.cnblogs.com/caodan01/p/14745562.html 一、动静分离 动静分离,通过中间件将动静请求和静态请求进行分离; 通过中间件将动态请求和静态请求分离,可以减少不必要的请求消耗,同时能减少请求的延时。 通过中间件将动态请求和静态请求分离,逻辑图如下:

                    [转帖]nginx(三十二)rewrite模块

                    一 官方rewrite模块 ① 模块涉及的指令 ② 基本简介 rewrite模块会根据'PCRE正则'匹配'重写URI' pcre下载地址 pcretest测试正则表达式 ③ break 疑惑点: 结束'该作用域'下剩余的指令,还是'只是该rewrite模块的'指令? 1)配置demo 2)不带参数

                    [转帖]日更第7日: (翻)nginx调优之使用return代替rewrite做重定向

                    https://www.jianshu.com/p/26dc6c2b5f43 解释说明 NGINX中重写url的能力是一个非常强大和重要的特性,从技术角度讲return与rewrite均能实现。但使用return相对rewrite更简单和更快,因为计算RegEx会产生额外的系统开销。 Return指

                    [转帖]nginx重定向(Redirect)- rewrite

                    语法:rewrite regex replacement [flag];; 默认值:—— 可配置段:server, location 作用:通过正则表达式的使用来改变URI。可以同时存在一个或多个指令。需要按照顺序依次对URL进行匹配和处理。 示例: rewrite ^/(.*) http://ww

                    [转帖]nginx实现内容重定向的两种方式:rewrite和反向代理

                    第一种:rewrite 更多参考另一个blog 按照常规理解,实现重定向就是要用rewrite来实现,例如demo: [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite01.confserver { listen 80; server_name cnblog

                    [转帖]nginx实现内容重定向的两种方式:rewrite和反向代理

                    第一种:rewrite 更多参考另一个blog 按照常规理解,实现重定向就是要用rewrite来实现,例如demo: [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite01.confserver { listen 80; server_name cnblog