• Nginx正则表达与Rewrite跳转


    Nginx正则表达与Rewrite跳转

    一.Location概述

    1.1Nginx三大模块

    http
    http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。
    server
    server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上只要运行一组Nginx进程,就可以运行多个网站。
    location
    location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。

    1.2Location正则表达

    匹配符含义
    ^匹配输入字符串的起始位置
    $匹配输入字符串的结束位置
    *匹配前面的字符零次或多次
    +匹配前面的字符一次或多次
    ?匹配前面的字符零次或一次
    .匹配除“\n”之外的任何单个字符
    \将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用
    转义字符含义
    \d匹配纯数字
    {n}重复 n 次
    {n,}重复 n 次或更多次
    {n,m}重复 n 到 m 次
    []定义匹配的字符范围
    [a]匹配单个字符 a
    [a-z]匹配 a-z 小写字母的任意一个
    [a-zA-Z0-9]匹配所有大小写字母或数字
    ()表达式的开始和结束位置
    或运算符

    location 大致可以分为三类:
    精准匹配:location = / {…}
    一般匹配:location / {…}
    正则匹配:location ~ / {…}

    location 常用的匹配规则:

    匹配规则
    =进行普通字符精确匹配,也就是完全匹配。
    ^~表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其它 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 相比,正则优先级更高

    1.3location 优先级:

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

    小结:

    (location = 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /)
    首先看 优先级:精确>前缀>正则>一般>通用
    优先级相同:正则看上下顺序,上面的优先;一般匹配看长度,最长匹配的优先
    精确、前缀、正则、一般 都没有匹配到,最后再看通用匹配

    1.3Location匹配规则

    实际生产中网站在使用中,至少有三个匹配规则定义:
    第一个必选规则
    直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。
    可以是一个静态首页,也可以直接转发给后端应用服务器

    location = / {
    root html;
    index index.html index.htm;
    }

    第二个必选规则
    处理静态文件请求,这是nginx作为http服务器的强项
    有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用

    location ^~ /static/ {
    root /webroot/static/;
    }
    location ~* .(html|gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
    }

    第三个规则
    通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器,非静态文件请求就默认是动态请求

    location / {
    procl_pass http://tomcat_server;
    }

    二.Rewrite

    2.1Rewrite概述

    rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。
    比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。

    rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用
    即: http://www.cl.com/abc/bbs/index.html?a=1&b=2 中的 /abc/bbs/index.html重写

    2.2Rewrite跳转实现

    Nginx:通过==ngx_http_rewrite_module ==模块支持URL重写、支持if条件判断,但不支持else
    跳转:从一个location跳转到另一个location,循环最多可以执行10次,超过后nginx将返回500错误
    PCRE支持:perl兼容正则表达式的语法规则匹配
    重写模块 set 指令:创建新的变量并设其值

    2.2.1执行顺序

    (1) 执行 server 块里面的 rewrite 指令。
    (2) 执行 location 匹配。
    (3) 执行选定的 location 中的 rewrite 指令。

    2.2.2语法格式

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

    flag标记说明

    标记描述
    last本条规则匹配完成后,继续向下匹配新的location URL规则,一般用在 server 和 if 中。
    break本条规则匹配完成即终止,不再匹配后面的任何规则,一般使用在 location 中
    redirect返回302临时重定向,浏览器地址会显示跳转后的URL地址
    permanent返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
    • last和break比较
    • 使用场景:
      last一般写在server和if中
      break一般用在location中
    • URL匹配:
      last不终止重写后的URL匹配
      break终止重写后的URL匹配

    三.Rewrite跳转

    3.1基于域名的跳转

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

    编辑配置文件
    vim /usr/local/nginx/conf/nginx.conf
    server {
            listen       80;
     	server_name  www.cl.com;  #域名地址 
     	charset utf-8;
     	access_log  /var/log/nginx/nginx.access.log;  #日志文件地址 
    location / {
    	#添加域名重定向 
             if ($host = 'www.cl.com'){      #$host为rewrite全局变量,代表请求主机头字段或主机名
              rewrite ^/(.*)$ http://www.chenlei.com/$1 permanent;  
    
    ^/(.*)为,域名下的所有,“.”匹配任意一字符,“*”匹配前面字符0或多次
    
             #$1为正则匹配的内容,即“域名/”之后的字符串-->(.*)      
          }
              root   html;
              index  index.html index.htm;
           }
    }
    
    echo "20.0.0.18 www.cl.com www.chenlei.com" >> /etc/hosts
    mkdir -p /var/log/nginx  #创建日志目录
    systemctl restart nginx
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    image-20220725142406825

    web验证输入www.cl.com

    image-20220725142843904

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

    现在访问的是 http://bbs.chenlei.com/post/,现在需要将这个域名下面的访问都跳转到http://www.chenlei.com/bbs/post/
    
    vim /usr/local/nginx/conf/nginx.conf
    server {
            listen       80;
      server_name  www.chenlei.com;  #域名地址 
      charset utf-8;
      access_log  /var/log/nginx/nginx.access.log;  #日志文件地址 
       
       location /post {
    	rewrite (.+) http://www.chenlei.com/bbs$1 permanent;
    	#将bbs.cl.com/post/(.+)跳转到新的域名地址;.+为一到多个字符
    	#$1为 /post/(.+) 
    	}
         location / {
                root   html;
                index  index.html index.htm;
            }
    
    mkdir -p /usr/local/nginx/html/bbs/post
    echo "

    测试页面

    "
    > /usr/local/nginx/html/bbs/post/index.html echo "20.0.0.18 bbs.chenlei.com">etc/host
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    web验证

    image-20220725154955765

    3.3基于客户端IP跳转

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

    编辑配置文件
    vim /usr/local/nginx/conf/nginx.conf
    server {
            listen       80;
            server_name  www.chenlei.com;
            charset utf-8;
            access_log  /var/log/nginx/nginx.access.log;
            set $rewrite true;   #设置rewrite变量值为true
            if ($remote_addr = "20.0.0.18"){  #当客户端为次ip时,不进行跳转
            set $rewrite false;                   #设置rewrite值为false
            }
            if ($rewrite = true){     #当rewrite值为真,则进行跳转 
            rewrite (.+) /test.html;  #将所有地址跳转到 www.chenlei.com/text.html界面
            }
            location / {
                root   html;
                index  index.html index.htm;
            }
    
    
    echo "

    正在测试中,请等待……

    "
    > /usr/local/nginx/htm/ltest.html systemctl restart nginx 使用192.168.48.10的IP主机访问域名 使用其它IP地址主机访问域名
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    image-20220725145230482

    web验证,用20.0.0.18机器访问

    image-20220725144440195

    其他机器或域名访问

    image-20220725144649343

    小bug本机用域名访问也会显示测试页面

    3.4基于参数匹配跳转

    现在访问http://www.chenlei.com/100-(100|200)-100.html 跳转到http://www.chenlei.com页面。
    
    vim /usr/local/nginx/conf/nginx.conf
    server {
    listen       80;
            server_name  www.cl.com;
            charset utf-8;
            access_log  /var/log/nginx/nginx.access.log;
      	if ($request_uri ~ ^/100-(100|200)-(\d+).html$) {
      	#$request_uri:包含请求参数的原始URI,不包含主机名
      	rewrite (.+) http://www.chenlei.com permanent;
      	}
        #location ~^ /100-(100|200)-(d+).html$ {
        #rewrite (.+) http://www.chenlei.com permanent;
      	#}
      	
      	location / {
      	root   html;
            index  index.html index.htm;
            }
    }
    
    systemctl restart nginx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    $request_uri:包含请求参数的原始URI,不包含主机名,如:http://www.cl.com/abc/bbs/index.html?a=1&b=2 中的 /abc/bbs/index.html
    $uri:这个变量指当前的请求URI,不包括任何参数,如:/abc/bbs/index.html
    documenturi:与uri相同,这个变量指当前的请求URI,不包括任何传递参数,如:/abc/bbs/index.html

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

    image-20220725145353077

    image-20220725150207465

    web测试

    image-20220725145659921

    image-20220725145836606

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

    要求访问 http://www.chenlei.com/chenlei/123.php 跳转到首页。
    
    vim /usr/local/nginx/conf/nginx.conf
    server {
    listen       80;
    	server_name  www.chenlei.com;  #域名修改 
    	charset utf-8;
     	access_log  /var/log/nginx/nginx.access.log;
    	location ~* /chenlei/.*\.php$ {	
    	rewrite (.+) http://www.chenlei.com permanent;
        	}
        	location / {
            root   html;
            index  index.html index.htm;
            }
    }
     systemctl restart nginx       
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    image-20220725150357769

    web验证

    浏览器访问:www.chenlei.com/chenlei/任意以php结尾的连接,跳转首页

    image-20220725150753609

    3.6基于URL请求跳转

    要求访问一个具体的页面如 http://www.chenlei.com/abc/123.html 跳转到首页
    
    vim /usr/local/nginx/conf/nginx.conf
    server {
    	server_name  www.chenlei.com;  #域名修改 
     	charset utf-8;
      	access_log  /var/log/nginx/nginx.access.log;
      	
     	location ~* ^/abc/123.html {
    	rewrite (.+) http://www.chenlei.com permanent;
    	}
    	
    	#if ($request_uri ~* ^/abc/123.html) {
     	#rewrite (.+) http://www.chenlei.com permanent;
    	#}
    	
    	location / {
            root   html;
            index  index.html index.htm;
     	}
    }
    systemctl restart nginx 	
    
    浏览器访问 http://www.chenlei.com/abc/123.html 跳转到http://www.chenlei.com页面。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    image-20220725150909744

    web验证

    image-20220725151144600

    四.总结

    在实际生产中,要熟练掌握location的匹配优先级(location = 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /)
    rewrite重写模块的使用,在实际生产中经常用到
    在实际使用中loication与if 有时可以互换,支持location匹配的可以使用if判断语句进行匹配,if与location的关系,有点类似于循环中的for与while
    😕/www.chenlei.com/abc/123.html 跳转到http://www.chenlei.com页面。

    
    [外链图片转存中...(img-WehTjpGV-1659058283400)]
    
    
    
    web验证
    
    [外链图片转存中...(img-2pJl4Kto-1659058283400)]
    
    
    
    ### 四.总结
    
    在实际生产中,要熟练掌握location的匹配优先级(location = 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /)
    rewrite重写模块的使用,在实际生产中经常用到
    在实际使用中loication与if 有时可以互换,支持location匹配的可以使用if判断语句进行匹配,if与location的关系,有点类似于循环中的for与while
    在使用if判断语句时,记得“=”两次的空格,切if判断语句不支持else
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    一.无人车导航:CMU团队开源自主导航和规划算法框架
    PostGIS导入shp文件报错:dbf file (.dbf) can not be opened.
    图纸管理制度《四》
    基于WAMP环境的简单用户登录系统实现(v3版)(持续迭代)
    【性能】如何计算 Web 页面的 TTI 指标
    结构体(Struct)
    Android主流插件化
    Vue项目使用echarts实现图表数据展示
    图论第2天----第1020题、第130题
    微信小程序中使用wx.showToast()进行界面交互
  • 原文地址:https://blog.csdn.net/weixin_43554927/article/details/126048858