1. Rewrite概述

  • 了解Rewrite

    rewrite和location的功能有点相像,都能实现跳转, 主要区别在于rewrite常用于同一域名内更改获取资源的路径, 而location是对一类路径做控制访问和反向代理,可以proxy_pass到其他服务器,在此说明下rewrite和location的执行先后顺序:

*46. Nginx跳转(rewrite) - 图1

  • Rewrite使用场景、实现原理。

    1.地址跳转:www.xuliangwei.com/class —> class.xuliangwei.com 2.协议跳转: http升级至https。 ( Rewrite方式来实现。 ) 3.URL静态化,将动态URL地址显示为静态URL地址的一种技术。

  • Rewrite URI重写配置语法
    1. set 设定变量
    2. if 条件判断
    3. return 返回数据
    4. rewrite 改变uri路径

*2.rewrite URI示例

2.1 if指令


[root@web01 ~]# cat /etc/nginx/conf.d/url.oldhou.org.conf
需求: 过滤 Nginx 请求中包含 a1=3526 的http请求 ——>>> 10.16.3.5 的 8080 端口处理。

  1. server {
  2. listen 80;
  3. server_name iftest.com;
  4. root /opt;
  5. location / {
  6. index index.html;
  7. #如果用户请求的uri中a1=3256,
  8. #我们通过反向代理代理到10.16.3.5:8080端口
  9. if ( $request_uri ~* 'a1=3256' ) {
  10. #proxy_pass http://10.16.3.5:8080; #这个地址是不存在的
  11. return 200 'ok....!'; #所以使用return来替代模拟
  12. }
  13. }
  14. }

测试的curl命令: curl -L -HHost:url.oldxu.com [http://10.0.0.7?a1=3256](http://10.0.0.7?a1=3256)
        -L 跟随跳转,追踪
        -H 指定Host头,具体要请求的域名是

2.2 set指令

  • 语法:

    set 设定变量 if 条件判断 需求1: 将用户请求url.oldxu.com.zh跳转至url.oldxu.com/zh

    1. 将用户请求url.oldxu.com.jp跳转至url.oldxu.com/jp

    rewrite 改变uri路径

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldhou.com.conf

server {
    listen 80;
    server_name url.oldhou.com.zh  url.oldhou.com.jp;

    location / {
        #判断用户请求的域名是zh还是jp
        if ( $http_host ~* "zh" ) {    #if  条件判断
            set $lang zh;                #set 设定变量
        }

        if ( $http_host ~* "jp" ) {
            set $lang jp;
        }

        #配置rewrite跳转规则
        rewrite ^/$ http://url.oldhou.com/$lang/  permanent;
         #^/$ 表示所有页面
    }
}

server {
    listen 80;
    server_name url.oldhou.com;
    root /opt;

    location / {
        index index.html;
    }
}

[root@web01 ~]# mkdir /opt/zh -p
[root@web01 ~]# mkdir /opt/jp -p
[root@web01 ~]# echo "zh.." > /opt/zh/index.html
[root@web01 ~]# echo "jp.." > /opt/jp/index.html
[root@web01 ~]# nginx -t
[root@web01 ~]# systemctl reload nginx

2.3 return 返回数据

  • 如果用户使用firefox访问url.oldxu.com [返回xxxx字符串]

    server {
      listen 80;
      server_name url.oldxu.com;
      root /opt;
      charset gbk,utf-8;
      location / {
          index index.html;
          default_type text/html;
          #判断用户使用的是否是firefox浏览器
          #如果是则返回一段话,如果不是则正常访问。
          if ( $http_user_agent ~* "firefox|MSIE" ) {
              return 200 'do not used firefox Browser!!!';
          }
      }
    }
    
  • 如果使用firefox访问,直接报错 500    [返回状态码]

    server {
      listen 80;
      server_name url.oldxu.com;
      root /opt;
      charset gbk,utf-8;
      location / {
          index index.html;
          default_type text/html;
          #判断用户使用的是否是 chrome浏览器
          #如果是则跳转500页面,如果不是则正常访问。
          if ( $http_user_agent ~* "firefox|MSIE" ) {
              return 500;
          }
      }
    }
    
  • 如果使用firefox访问,直接跳转至浏览器下载页面。
     http://www.firefox.com.cn/ [返回一个url地址]

    server {
      listen 80;
      server_name url.oldxu.com;
      root /opt;
      charset gbk,utf-8;
      location / {
          index index.html;
          default_type text/html;
          #判断用户使用的是否是 chrome浏览器
          #是则返回一个url地址。不是则正常访问原地址。
          if ( $http_user_agent ~* "firefox|MSIE" ) {
              return 302 http://www.firefox.com.cn;
          }
      }
    }
    

    ps: rewrite 重写URL、或者说是用来做URL地址跳转的。 PS: return 主要用来返回数据 | 返回字符串 | 返回url地址。 跳转应用:(2种方法) image.png

2.4 Rewrite 跳转页面

image.png

last与break区别

server {
    listen 80;
    server_name url.etiantian.org;
    root /code;

    location / {
        rewrite /1.html /2.html     #break;   ----> 最终返回的就是2.html   #last(停止向下rewrite,直接请求url.etiantian.org/2.html) --->最终返回a.html
        rewrite /2.html /3.html;
    }

    location /2.html {
        rewrite /2.html /a.html;
    }

    location /3.html {
        rewrite /3.html /b.html;
    }
}

last: 匹配成功,停止继续匹配。 请求的是1.HTML,最终的访问结果是a.html 因为:在location{}内部,遇到last,本location{}内后续指令不在执行。 匹配成功后,会重新像Server{}标签发起请求,从头到尾在匹配一遍规则,那个匹配则执行哪个。 break: 匹配成功,停止继续匹配。 请求的是1.HTML,最终的访问结果是2.html 因为:在location {} 内部遇到了break,本location内以及后面的所有的location{}内的指令都不在执行。

区别总结

当rewrite规则遇到last后, 本location{}里后续rewrite/return规则不执行,但重写后的url再次从头开始执行所有规则,哪个匹配执行哪个。

当rewrite规则遇到break后 本location{}与其他location{}的所有rewrite/return规则都不再执行。

permanent与redirc区别

http—https场景下:

permanent: 状态码301 永久跳转。 新跳转的网站有排名,旧网站排名会被清空。(浏览器会记住跳转的过程) 1.html(排名会被清空) 2.html(有排名) redirect: 状态码302 临时跳转。 旧网站排名无影响,新网站没有排名。 1.html(不影响) 2.html(没有排名)

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /code;

    location / {
        rewrite /1.html /2.html permanent;
    }
}

2.4.2 Rewrite案例。

需求1: 根据用户浏览器请求头中携带的语言调度到不同的页面。

url.oldxu.com [ 中国人看到的是 你好 | 国外人看到的是 hello。] 中国人: zh      日本: jp

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf1

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    #判断浏览器语言
    if ($http_accept_language ~* "zh|zh-cn" ) {
        set $language /zh;
    }

    if ($http_accept_language ~* "jp|ja" ) {
        set $language /jp;
    }

    #rewrite跳转
    rewrite  ^/$ $language;

    location / {
        index index.html;
    }
}

需求2: 用户通过手机设备访问 url.oldxu.com,跳转至url.oldxu.com/m

https://www.xhqb.com https://www.xhqb.com/m/

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    #判断是否是手机
    if ($http_user_agent ~* 'android|iphone|ipad') {
        rewrite ^/$ /m last;    
    }
    location / {
        index  index.html;
    }
}

需求3: 用户通过手机设备访问 url.oldxu.com 跳转至 m.oldxu.com

url.oldxu.com m.oldxu.com

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

#判断是否是手机
if ($http_user_agent ~* 'android|iphone|ipad') {
        rewrite ^/$ http://m.oldxu.com redirect;
    }

    location / {
        index  index.html;
    }
}

server {
    listen 80;
    server_name m.oldxu.com;
    root  /opt/m;

    location / {
        index index.html;
    }
}

需求4: 用户通过http协议请求,能自动跳转至https协议。

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    #书写的方式很多
    #rewrite ^(.*)$ https://$server_name$1;
    return 302 $https://$server_name$request_uri;

}

需求5: 网站在维护过程中,希望用户访问所有网站重定向至一个维护页面。

( 在不变动nginx配置的情况下,进入维护页面。)

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    #维护状态
    rewrite ^(.*)$ /wh.html break;

    location / {
        index index.html;
    }
}

需求6: 当服务器遇到 403 404 502 等错误时,自动转到临时维护的静态页

( 搜一些不存在的页面时,服务器会返回 孩子丢失的信息。https://404.life/ )

[root@web01 ~]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    location / {
        index index.html;
    }
    error_page 403 404 502 = @tempdown;
    location @tempdown {
        rewrite ^(.*)$ /wh.html break;
    }
}

——-> 错误页面模板

[root@web01 error_page]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    location / {
        index index.html;
    }

    #碰到403 404 502 -->tempdown,tempdown内部重定向
    error_page 403 404 502 = @tempdown;
    location @tempdown {
        root /opt/error_page;
        rewrite ^(.*)$ /index.html break;
    }

}

需求7: 公司网站在停机维护时,指定的IP能够正常访问,其他的IP跳转到维护页。

( 学生 ) 10.0.0.1 可以访问,除此以外所有人都不能访问。 我们需要借助多个判断。

  • 方式一

[root@web01 error_page]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;
    #初始一个变量为0
    set $ip 0;

    #判断来源IP是自己公司的服务器地址,则将ip变量设定为1
    if ($remote_addr ~ "10.0.0.1|10.0.0.2") {
        set $ip 1;
    }
    #判断如果ip变量判断是0,我们直接进入维护页面。
    if ($ip = 0) {
        rewrite ^(.*)$ /wh.html  break;
    }

    location / {
        index index.html;
    }
}
  • 方式二

[root@web01 error_page]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;


    location / {
        index index.html;
        allow 10.0.0.7/32;
        deny all;
    }

    location /error_page {
        root /opt;
    }


    error_page 403 = @temp;
    location @temp {
        return 302 'http://url.oldxu.com/error_page/index.html';
    }
}

需求8: 公司网站后台/admin,只允许公司的出口公网IP可以访问

( 10.0.0.1 ),其他的IP访问全部返回500,或直接跳转至首页。

[root@web01 error_page]# cat /etc/nginx/conf.d/url.oldxu.com.conf

server {
    listen 80;
    server_name url.oldxu.com;
    root /opt;

    location / {
        index index.html;
    }

    location /admin {
        index index.html;

    #设定一个初始变量,变量名为ip,变量的值为0
        set $ip 0;
    #判断来源的用户IP是多少,如果是10.0.0.7,则将变量名ip的值重置为1
        if ($remote_addr ~ "10.0.0.7") {
            set $ip 1;
        }
    #判断ip变量为0的,直接500拒绝。
        if ($ip = 0) {
            #return 500;
            return 302 'https://www.xuliangwei.com';
        }
    }
}

ps:除了域名以外的都叫uri ~* 忽略大小匹配 ^/$ 代表整个页面