背景
这一章我们来一起聊聊Nginx的Rewrite的功能,Rewrite用于对请求的URL进行重写,然后返回重定向或有条件地选择配置上。后续我们需要了解的Nginx的HTTPS的功能也是基于Rewrite之上的。接下来我们展开说说吧。
Rewrite详解
1. 什么是Rewrite?
Rewrite主要实现URL地址的重写,以及URL地址的跳转;即:就是将用户请求web服务器的URL地址重新修改为其他URL地址的过程。
2. Rewrite的应用场景
2.1 地址跳转:比如当用户访问的xhz.com/edu这个URL时,将其重定向到一个新的域名edu.xhz.com。
2.2 协议跳转:当用户通过http的请求协议重新跳转至https协议(实现https的主要手段)。
2.3 URL静态化:将动态URL地址显示为静态URL的一种技术,能提高搜索引擎的抓取,并能减少动态URL对外暴露过多的参数。(Rewrite会轻微增加服务器的负担)。
3. 如何实现?
通过ngx_http_rewrite_module模块支持url重写、支持if条件判断,但不支持else。另外该模块需要PCRE支持,应在编译nginx时指定PCRE支持。根据相关变量重定向和选择不同的配置,从一个location跳转到另一个location,不过这样的循环最多可以执行10次,超过后nginx将返回500错误。同时,重写模块包含set指令,来创建新的变量并设其值,如记录条件标识、传递参数到其他location、记录做了什么等等。
ngx_http_rewrite_module官网:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
4. Rewrite参数
4.1 break
只执行break所在的指令,停止执行break后续的所有指令。
1
2
3
4
5
6
7
8
9
10
11### 语法 Syntax: break; Default: — Context: server, location, if ### 示例 if ($slow) { limit_rate 10k; break; }
4.2 if
对给定的条件(condition)进行判断,如果条件为真,大括号内的rewrite指令将被执行。
1
2
3Syntax: if (condition) { ... } Default: — Context: server, location
condition条件可以满足如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14***当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false; 1. 使用“=”和“!=”比较一个变量和字符串; 2. 使用“~”做正则表达式匹配,“~*”做不区分大小写的正则匹配,“!~”做区分大小写的正则不匹配; 3. 使用“-f”和“!-f” 检查一个文件是否存在; 4. 使用“-d”和“!-d”检查一个目录是否存在; 5. 使用“-e”和“!-e”检查一个文件、目录、符号链接是否存在; 6. 使用“-x”和“ !-x”检查一个文件是否可执行;
示例:
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
27
28
29
30
31
32
33
34
35
36
37
38
39// 当请求头中的User-Agent中包含MSIE(~区分大小写)时rewrite请求到/msie/$1目录下,$1表示匹配的URI if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } // 当请求头中的cookie匹配正则的时候,将设置变量$id 为$1 其中$1= =([^;]+)(?:;|$)匹配到的内容 if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; } // 当请求头中的请求类型method是POST的时,直接返回405 if ($request_method = POST) { return 405; } //如果$slow可以通过set指令设置,则进行限速处理 if ($slow) { limit_rate 10k; } // 如果为真,则返回403 if ($invalid_referer) { return 403; } //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查 if (!-f $request_filename){ break; proxy_pass http://127.0.0.1; } //如果请求头中包含"post=140",则重定向到example.com if ($args ~ post=140){ rewrite ^ http://example.com/ permanent; }
上诉示例来自nginx的官网,可以发现在匹配的过程中主要还是正则表达式,在来回顾下正则。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19= 精准匹配 ^~ 以某个字符串开头 ~ 区分大小写的正则匹配 / 通用匹配,任何请求都会匹配到 ~* 不区分大小写的正则匹配 . :匹配除换行符以外的任意字符 ? :重复0次或1次 + :重复1次或更多次 * :重复0次或更多次 d :匹配数字 ^ :匹配字符串的开始字符 $ :匹配字符串的结束字符 {n} :重复n次 {n,} :重复n次或更多次 [c] :匹配单个字符c [a-z] :匹配a-z小写字母的任意一个
4.3 return
停止处理并为客户端返回状态码,非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204,400,402-406,408,410, 411, 413, 416与500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头部值。没有状态码的URL将被视为一个302状态码。此外,可以将带有代码 302 的临时重定向 URL 指定为唯一参数。此类参数应以“http://”、“https://”或“$scheme”字符串开头。 URL 可以包含变量。
1
2
3
4
5Syntax: return code [text]; return code URL; return URL; Default: — Context: server, location, if
4.4 rewrite
如果指定的正则表达式与请求 URI 匹配,则 URI 将按照替换字符串中的指定进行更改。重写指令按照它们在配置文件中出现的顺序依次执行。可以使用标志终止对指令的进一步处理。如果替换字符串以“http://”、“https://”或“$scheme”开头,则处理停止并将重定向返回给客户端。
1
2
3
4
5
6
7
8
9
10
11
12Syntax: rewrite regex replacement [flag]; Default: — Context: server, location, if regex : 正则表达 replacement : 重定向的内容 [flag]: 标志位,包含:last,break,redirect,permanent
regex和replacement没什么具体可说的,后续我们通过示例进行理解就行,主要是flag的参数是什么含义,我们需要了解下。我们先看个示例吧!
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60//当通过www.xhz_rewrite.com/1.html访问时,此时通过rewrite返回的结果为b.html中的内容。 server { listen 80; server_name xhz_rewrite.com www.xhz_rewrite.com; root /rewrite; location / { rewrite /1.html /2.html; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; } } //当通过www.xhz_rewrite.com/1.html访问时,此时通过rewrite返回的结果为2.html中的内容。 server { listen 80; server_name xhz_rewrite.com www.xhz_rewrite.com; root /rewrite; location / { rewrite /1.html /2.html break; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; } } //当通过www.xhz_rewrite.com/1.html访问时,此时通过rewrite返回的结果为a.html中的内容。 server { listen 80; server_name xhz_rewrite.com www.xhz_rewrite.com; root /rewrite; location / { rewrite /1.html /2.html last; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; } }
总结:
break:完成该rewrite规则的执行后遇到break就会终止后所有指令的执行。
last:完成该rewrite规则的执行后遇到last,就会将重写后的URI,重server开头开始匹配,匹配到哪个就执行哪个。
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//通过 www.xhz_rewrite.com/1.html访问,放回的结果是3.htnl的内容,返回的转态码为301 server { listen 80; server_name xhz_rewrite.com www.xhz_rewrite.com; root /rewrite; location / { rewrite /1.html /2.html permanent; rewrite /2.html /3.html; } } //通过 www.xhz_rewrite.com/1.html访问,放回的结果是3.htnl的内容,返回的转态码为302 server { listen 80; server_name xhz_rewrite.com www.xhz_rewrite.com; root /rewrite; location / { rewrite /1.html /2.html redirect; rewrite /2.html /3.html; } }
总结:
redirect:返回302临时重定向,地址栏会显示跳转后的地址;
permanent:返回301永久重定向,地址栏会显示跳转后的地址;即表示如果客户端不清理浏览器缓存,那么返回的结果将永久保存在客户端浏览器中了。因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return
Rewrite实例
1. 根据浏览器的语言不同调度到不同的页面中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18server { listen 80; server_name xhz_chinese.com www.xhz_chinese.com; root /rewrite; location / { if ($http_accept_language ~* "zh-CN|zh") { set $language zh; } if ($http_accept_language ~* "en") { set $language en; } rewrite ^/$ /$language; } }
2. 通过手机访问xhz.iphone.com跳转到xhz.iphone.com/test
1
2
3
4
5
6
7
8
9
10
11
12server { listen 80; server_name xhz_iphone.com www.xhz_iphone.com; root /rewrite/iphone; location / { if ($http_user_agent ~* "iphone|android|ipad") { rewrite ^/$ /test; } } }
3. 通过收集手机xhz.test.com跳转到edu.xhz.test.com
1
2
3
4
5
6
7
8
9
10
11
12
13server { listen 80; server_name xhz123.com www.xhz123.com; root /rewrite/xhz123; location / { index index.html; if ($http_user_agent ~* "iphone|android|ipad") { rewrite ^/$ http://edu_xhz_iphone.com; } } }
4. 通过http协议请求,自动跳转到https协议。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16server { listen 80; server_name xhz_https.com www.xhz_https.com; root /rewrite/https; location ^(.*)$ { rewrite ^(.*)$ https://$server_name$1 redirect; } } server { listen 443 default; server_name xhz_https.com www.xhz_https.com; }
5. 网站维护过程中,希望用户访问所有网站都重定向到一个维护页面。
1
2
3
4
5
6
7
8
9
10
11server { listen 80; server_name xhz_wh.com www.xhz_wh.com; root /rewrite/wh; rewrite ^(.*)$ /wh.html break; location / { index index.html; } }
6. 单服务器遇到403 404 502等错误时,自动跳转到临时维护的静态页面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15server { listen 80; server_name xhz_static.com www.xhz_static.com; root /rewrite/static; location / { index index.html; } error_page 404 403 502 = @err_html location @err_html { rewrite ^(.*)$ /static.html break; } }
7. 公司网站在停机维护时,指定ip能正常访问,其他ip跳转到维护页面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21server { listen 80; server_name bind_ip.com www.bind_ip.com; root /rewrite/bind_ip; set $ip 0; if ($remote_addr = '192.168.65.2|192.168.65.3') { set $ip 1; } if ($ip = '0') { rewrite ^(.*)$ /bind_ip.html break; } ## 如果想针对耨个location进行操作,则将如上配置写入location中即可 location / { index index.html; } }
8. 公司网站后台/admin,只允许公司的出口公网ip可以访问,其他ip访问全部返回500
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18server { listen 80; server_name admin.com www.admin.com; root /rewrite/; location /admin { set $ip 0; if ($remote_addr = ' 113.57.152.160| 113.57.152.161') { set $ip 1; } if ($ip = '0') { return 500; } index index.html; } }
最后
以上就是单薄保温杯最近收集整理的关于Nginx的Rewrite详解(七)背景 Rewrite详解Rewrite实例的全部内容,更多相关Nginx内容请搜索靠谱客的其他文章。
发表评论 取消回复