目录

一、nginx rewrite概述

1、概述

2、Rewrite跳转场景

3、Rewrite跳转实现

4、Rewrite实际场景

二、Nginx常见模块

三、常见的Nginx正则表达式

1、正则的优势

2、正则的作用

四、Rewrite语法

1、flag标记说明

2、last和break比较

3、rewrite执行顺序

五、location

1、location大致可以分为三类

2、location常用的匹配规则

3、location优先级排列说明

示例

4、location 匹配顺序

5、三个匹配规则定义

  rewrite和location区别

六、rewrite 示例

1、基于域名的跳转

2、 基于客户端 IP 访问跳转

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

4、基于参数匹配跳转

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

6、基于URL请求跳转

七、总结


一、nginx rewrite概述

1、概述

URL:就是一个具体路径/位置

URI:指的是一个拥有相同类型/特性的对象集合

​location是为了匹配访问的路径(URL)​
 
​if 做为分支判断,并且if分支,仅支持单分支​
 
​rewrite:对访问路径进行改写大分支:​
 
​1、改写的路径​
 
​在Nginx服务器上-改写路径​
 
​2、​改写的路径​
 
​在后端/其他服务器上-跳转​

2、Rewrite跳转场景

  • URL看起来更规范、合理
  • ​企业会将动态URL地址伪装成静态地址提供服务
  • 网址换新域名后,让旧的访问跳转到新的域名上
  • 服务端某些业务调整

3、Rewrite跳转实现

  • Nginx是通过ngx_http_rewrite_module模块支持url重写、支持if条件判断,但不支持else。
  • 另外该模块需要 PCRE支持,应在编译Nginx时指定PCRE 支持,默认已经安装。
  • 根据相关变量重定向和选择不同的配置,从一个location跳转到另一个location,不过这样的循环最多可以执行10次,超过后Nginx将返回500错误。
  • 重写模块包含set指令,来创建新的变量并设其值,这在有些情景下非常有用的,如记录条件标识、传递参数到其他location、记录做了什么等等。
  • rewrite功能就是使用Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。​

4、Rewrite实际场景

  • 使用rewrite进行匹配跳转(防盗链)
  • 使用if匹配全局变量后跳转
  • 使用location匹配再跳转(匹配的访问 路径URL location可以匹配本地的重写以及跨服务器的跳转)

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

  • (多个server模块 sever模块里包含location location包含if if里面包含rewrite)
  • location只对域名后边的除去传递参数外的字符串起作用

对域名或参数字符串

  • 使用if全局变量匹配
  • 使用proxy_pass反向代理

二、Nginx常见模块

  • http

http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。

  • server

server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上只要运行一组Nginx进程,就可以运行多个网站。

  • location

location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。

三、常见的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、正则的作用

  • Nginx作为运维角度前段接受、想用客户请求的直接对服务器所以需要考虑到Nginx的执行效率(精确匹配-类比)、性能(资源消耗)、抗压能力(高并发时处理能力)、用户体验感(用户访问群体)

四、Rewrite语法

rewrite < regex > < replacement > [flag]
regex:正则表达式
replacement :跳转后的内容
flag:rewrite支持的flag标记

1、flag标记说明

标记说明
last相当于Apache的【L】标记,表示完成rewrite
break本条规则匹配完成即终止,不在匹配后面的任何规则
redirect返回302临时重定向,浏览器地址栏会显示跳转后的URL地址,爬虫不会更新url
permanent返回301永久重定向,浏览器地址栏会显示跳转后的URL地址,爬虫更新url

2、last和break比较

lastbreak
使用场景一般写在server和 if中一般使用在location中
URL匹配不重质重写后的url匹配终止重写后的url匹配

3、rewrite执行顺序

执行server块里面的rewrite指令

执行location匹配

执行选定的location中的rewrite指令

五、location

1、location大致可以分为三类

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

2、location常用的匹配规则

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

3、location优先级排列说明

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

优先级结论

(location = 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (location /)

示例

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

location = / {}

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

location / {}

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

location /documents/ {}

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

location /documents/abc {}

5、匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条

location ^~ /images/ {}

6、匹配所有以 gif、jpg或jpeg 结尾的请求
然而,所有请求 /images/ 下的图片会被 location /images/ 处理,因为 的优先级更高,所以到达不了这一条正则。

location ~* \.(gif|jpg|jpeg)$ {}

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

location /images/abc {}

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

location ~ /images/abc {}

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

location /images/abc/1.html {}

4、location 匹配顺序

首先看 优先级:精确>前缀>正则>一般>通用
优先级相同:正则看上下顺序,上面的优先;一般匹配看长度,最长匹配的优先
精确、前缀、正则、一般都没有匹配到,最后再看通用匹配

5、三个匹配规则定义

实际网站使用中,至少有三个匹配规则定义

直接匹配网站根

第一个必选规则直接匹配网站根
通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。
可以是一个静态首页,也可以直接转发给后端应用服务器
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 / {
    proxy_pass http://tomcat_server;
}

rewrite和location区别

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

六、rewrite 示例

1、基于域名的跳转

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

#####将 http 重定向 https。
server {
        listen       80;
        server_name  www.liy.com;
###      return 301 https://$server_name$request_uri;
        charset koi8-r;

        location / {
        if ($host = "www.liy.com") {            #$host为rewrite全局变量,代表请求主机头字段或主机名
                rewrite ^/(.*)$ https://www.yongbu.top/$1 permanent;  #$1为正则匹配的内容,即“域名/”之后的字符串
        }
}
}




    server {
             #SSL 访问端口号为 443
        listen       443 ssl;
        server_name  www.liy.com;
        charset utf-8;
        access_log /var/log/nginx/liy.com.access.log;
          #证书文件名称
        ssl_certificate      /usr/local/nginx/conf/cert/7850872_www.yongbu.top.pem;
                                                                   私钥文件名称
        ssl_certificate_key  /usr/local/nginx/conf/cert/7850872_www.yongbu.top.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;             #缓存有效期
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;         #安全链接可选的加密协议
         #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。        
ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    
        ssl_prefer_server_ciphers on;             #使用服务器端的首选算法
        root html;
        index  index.html index.htm;
        }
}
     

测试

2、 基于客户端 IP 访问跳转

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

编辑配置文件
vim /usr/local/nginx/conf/nginx.conf

    server {
        listen       80;
        server_name  www.liy.com;
#       return 301 https://$server_name$request_uri;
        charset koi8-r;
        set $rewrite true;            #设置rewrite变量值为true
        if ($remote_addr = '192.168.58.10'){    #当客户端IP为192.168.58.10时,将变量值设为false,不进行重写

        set $rewrite false;
}
 #设置是否合法的IP标记
        if ($rewrite = true) {         #设置变量$rewrite,变量值为boole值true
        rewrite (.+) /weihu.html;    #当rewrite值为真,则进行跳转 
}
        location = /weihu.html {        
#       if ($host = "www.liy.com") {
                rewrite ^/(.*)$ https://www.yongbu.top/$1 permanent;  ##http重定向到https
#       }
}
}

....
....
...

    server {
        listen       443 ssl;
        server_name  www.yongbu.top;
        charset utf-8;
        access_log /var/log/nginx/liy.com.access.log;
        ssl_certificate      /usr/local/nginx/conf/cert/7850872_www.yongbu.top.pem;
        ssl_certificate_key  /usr/local/nginx/conf/cert/7850872_www.yongbu.top.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_prefer_server_ciphers on;
        root html;
        index  index.html index.htm;
        }
}

测试

使用192.168.58.10的IP主机访问域名

只有 IP 为 192.168.223.10 能正常访问,其它地址都是维护页面

其他机器(192.168.58.19)添加域名映射

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

现在访问的是 http://bbs.liy.com/test/new.html,现在需要将这个域名下面的访问都跳转到https://www.yongbu.top/bbs/

vim /usr/local/nginx/conf/nginx.conf
...
...
    server {
        listen       80;
        server_name  bbs.liy.com;
        charset utf-8;
        location /test {
        rewrite (.+) https://www.yongbu.top/bbs$1 permanent;        ##重定向到https
   #将bbs.liy.com/test/new.html  (.+)跳转到新的域名地址;.+为一到多个字符
	#$1为 /test/(.+) 
}
}
        
     ####https配置   
    server {
        listen       443 ssl;
        server_name  www.liy.com;
        charset utf-8;
        access_log /var/log/nginx/liy.com.access.log;
        ssl_certificate      /usr/local/nginx/conf/cert/7850872_www.yongbu.top.pem;
        ssl_certificate_key  /usr/local/nginx/conf/cert/7850872_www.yongbu.top.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_prefer_server_ciphers on;
        location / {
        root html;
        index  index.html index.htm;
        }
}
}

测试

登录服务器查看域名是否跳转
访问源域名/test/new.html文件

4、基于参数匹配跳转

现在访问http://www.liy.com/100-(100|200)-100.html 跳转到https://www.yongbu.top页面。

vim /usr/local/nginx/conf/nginx.conf
...
...
    server {
        listen       80;
        server_name  www.yong.com;
        charset utf-8;
        if ($request_uri ~ ^/100-(100|200)-100.html$) {
        rewrite (.+) https://www.yongbu.top permanent;
        }

}

...
...
server {
        listen       443 ssl;
        server_name  www.liy.com;
        charset utf-8;
        access_log /var/log/nginx/liy.com.access.log;
        ssl_certificate      /usr/local/nginx/conf/cert/7850872_www.yongbu.top.pem;
        ssl_certificate_key  /usr/local/nginx/conf/cert/7850872_www.yongbu.top.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_prefer_server_ciphers on;
        location / {
        root html;
        index  index.html index.htm;
        }
}
}

重启服务

测试

浏览器访问 http://www.liy.com/100-(100|200)-100.html 跳转到https://www.yongbu.top页面

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

要求访问 http://www.liy.com/test/123.php 跳转到首页。

vim /usr/local/nginx/conf/nginx.conf
...
...
    server {
        listen       80;
        server_name  www.liy.com;
        charset utf-8;
        location ~* /test/.*\.php$ {
        if ($host = "www.liy.com") {
        rewrite (.+) https://www.yongbu.top permanent;
        }
}
}
   

...
...
    server {
        listen       443 ssl;
        server_name  www.liy.com;
        charset utf-8;
        access_log /var/log/nginx/liy.com.access.log;
        ssl_certificate      /usr/local/nginx/conf/cert/7850872_www.yongbu.top.pem;
        ssl_certificate_key  /usr/local/nginx/conf/cert/7850872_www.yongbu.top.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_prefer_server_ciphers on;
        location / {
        root html;
        index  index.html index.htm;
        }
}
}
                                   

重启服务

测试

浏览器访问 http://www.liy.com/test/123.php 跳转到https://www.yongbu.top页面。

6、基于URL请求跳转

要求访问一个具体的页面如 http://www.liy.com/abc/123.html 跳转到首页

使用if 判断跳转

vim /usr/local/nginx/conf/nginx.conf
...
...
    server {
        listen       80;
        server_name  www.liy.com;
        charset utf-8;
        if ($request_uri ~* ^/abc/123.html) {
        rewrite (.+) https://www.yongbu.top redirect;
        }

}

...
...
    server {
        listen       443 ssl;
        server_name  www.liy.com;
        charset utf-8;
        access_log /var/log/nginx/liy.com.access.log;
        ssl_certificate      /usr/local/nginx/conf/cert/7850872_www.yongbu.top.pem;
        ssl_certificate_key  /usr/local/nginx/conf/cert/7850872_www.yongbu.top.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_prefer_server_ciphers on;
        location / {
        root html;
        index  index.html index.htm;
        }
}
}

重启服务

测试

 浏览器访问 http://www.liy.com/abc/123.html 跳转到https://www.yongbu.top页面。

七、总结

在实际生产中,要熟练掌握location的匹配优先级(location = 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /),通过实验我们将HTTP重定向到https,https使数据传输更加安全。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐