一、常见的 Nginx 正则表达式
在 Nginx 配置中,正则表达式用于匹配和重写 URL 请求。以下是一些常见的 Nginx 正则表达式示例:
当涉及正则表达式时,理解各个特殊字符的含义是非常重要的。以下是每个特殊字符的例子:
-
^
:匹配输入字符串的起始位置- 示例:
^hello
匹配以 "hello" 开头的字符串, - 示例:
^/(user|profile)
: 匹配以 "/user" 或 "/profile" 开头的 URI。
- 示例:
-
$
:匹配输入字符串的结束位置- 示例:
world$
匹配以 "world" 结尾的字符串
- 示例:
-
*
:匹配前面的字符零次或多次- 示例:
colou*r
匹配 "color" 或 "colour"
- 示例:
-
+
:匹配前面的字符一次或多次- 示例:
go+l
匹配 "gol", "gool", "gooool", 等等
- 示例:
-
?
:匹配前面的字符零次或一次- 示例:
apple(s)?
匹配 "apple" 或 "apples"
- 示例:
-
.
:匹配除 "\n" 之外的任何单个字符- 示例:
b.t
匹配 "bat", "but", "b@t", 等等
- 示例:
-
\
:将后面接着的字符标记为一个特殊字符- 示例:
\.jpg$
: 匹配以 ".jpg" 结尾的 URI。 - 示例:
\d+
匹配一个或多个数字
- 示例:
-
{n}
:重复 n 次- 示例:
a{3}
匹配 "aaa"
- 示例:
-
{n,}
:重复 n 次或更多次- 示例:
b{2,}
匹配 "bb", "bbb", "bbbb", 等等
- 示例:
-
{n,m}
:重复 n 到 m 次- 示例:
c{2,4}
匹配 "cc", "ccc", "cccc"
- 示例:
-
[]
:定义匹配的字符范围- 示例:
[aeiou]
匹配任何一个元音字母 - 示例:
[0-9]
匹配任何一个数字
- 示例:
-
[c]
:匹配单个字符 c- 示例:
[abc]
匹配 "a", "b", 或 "c"
- 示例:
-
[a-z]
:匹配 a-z 小写字母的任意一个- 示例:
[a-z]
匹配任何一个小写字母
- 示例:
-
[a-zA-Z0-9]
:匹配所有大小写字母或数字- 示例:
[a-zA-Z0-9]
匹配任何一个大小写字母或数字
- 示例:
-
()
:表达式的开始和结束位置- 示例:
(abc)
匹配 "abc"
- 示例:
-
|
:或运算符- 示例:
cat|dog
匹配 "cat" 或 "dog"
- 示例:
这些正则表达式可用于识别特定的 URL 模式,并据此进行重定向或其他操作。
二、Nginx Location基本操作
2.1 Location 大致可以分为三类
在 Nginx 配置中,location 主要分为三类:精确匹配、前缀匹配和正则表达式匹配。
- 精确匹配:指定完整的 URI 进行匹配。location = / {...}
- 前缀匹配:指定 URI 的前缀进行匹配。location / {...}
- 正则表达式匹配:使用正则表达式进行匹配。正则匹配:location ~ / {...}
示例:
location = /about {# 精确匹配
}location /blog/ {# 前缀匹配
}location ~* \.(gif|jpg|jpeg)$ {# 正则表达式匹配
}
这些不同的匹配规则使得我们能够根据不同的需求来灵活地配置服务器。
2.2 Location 常用的匹配规则
在 location 中,有一些常用的匹配规则,例如:
=
: 精确匹配。也就是完全匹配^~
: 前缀匹配,如果匹配成功,停止搜索其他 location。~
和~*
: 区分大小写和不区分大小写的正则表达式匹配。- !~ :区分大小写的匹配取非。!~* :不区分大小写的匹配取非。
这些匹配规则决定了如何匹配 URI,并且影响着 location 的优先级。
2.3 Location 优先级
在 Nginx 中,location 的优先级遵循“先精确匹配,再前缀匹配,最后正则表达式匹配”的原则。这意味着精确匹配的 location 会优先匹配,其次是前缀匹配,最后是正则表达式匹配。
2.4 Location 示例说明
假设我们有以下几个 location 规则:
location = /about { # 精确匹配 }location /blog/ { # 前缀匹配 }location ~* \.(gif|jpg|jpeg)$ { # 正则表达式匹配 }
当请求 URI 为 "/about" 时,将匹配第一个规则,因为它是精确匹配。请求 URI 为 "/blog/some-article" 时,将匹配第二个规则,因为它是前缀匹配。而请求 URI 为 "/image.jpg" 时,将匹配第三个规则,因为它是正则表达式匹配。
location = / {# 这里匹配根目录的请求,不包括任何额外的路径# =为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配
}location /user/ {# 匹配以 /user/ 开头的所有请求,比如 /user/profile、/user/settings 等# 匹配任何以 /user/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
}location ~* \.(css|js)$ {# 匹配所有以 .css 或 .js 结尾的请求,不区分大小写
}location ^~ /admin {# 匹配以 /admin 开头的请求,并且停止匹配其它正则规则
}location ~ ^/article/(\d+) {# 匹配类似 /article/123、/article/456 这样的数字结尾的请求
}
2.5 Location 匹配顺序
在 Nginx 中,location 的匹配顺序非常重要。通常情况下,应该按照从精确匹配到前缀匹配再到正则表达式匹配的顺序进行配置,以确保匹配的准确性。
2.6 三个匹配规则定义
2.6.1 直接匹配网站根
第一个必选规则直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网,可以是一个静态首页,也可以直接转发给后端应用服务器
对于直接匹配网站根的需求,可以使用如下配置:
location = / { # 处理根目录请求 root html;index index.html index.htm;
}
2.6.2 处理静态文件请求
第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
静态文件通常位于特定的目录中,可以使用前缀匹配来处理静态文件请求:
目录匹配:
location /static/ { # 处理静态文件请求 root /usr/share/nginx/html/;index index.html index.htm;try_files $uri $uri/ /dp/index.html = systemUpdate;
}
后缀匹配:
location ~* \.(xlsx|jpg)$ { # 处理特定类型的请求 root /usr/share/nginx/html/file;
}
2.6.3 通用规则
第三个规则就是通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器
非静态文件请求就默认是动态请求
location / {proxy_pass http://127.0.0.1:8080;
}
通过以上配置示例,我们可以更好地理解 Nginx 中 location 的匹配规则和优先级。
三、Nginx Rewrite基本操作
rewrite 功能是利用 Nginx 提供的全局变量或自定义变量,结合正则表达式和标志位来实现 URL 的重写和重定向。它通常用于处理域名更换后的跳转、页面地址变更的重定向、网站防盗链等需求。
rewrite 指令可以放置在 server、location 和 if 块中,它默认只对域名后面除了传递的参数之外的字符串进行匹配重写。比如,对于 URL http://www.baidu.com/abc/bbs/index.php?a=1&b=2
,rewrite 只会对 /abc/bbs/index.php
部分进行重写。
下面是 rewrite 的语法格式:
rewrite <regex> <replacement> [flag];
其中:
regex
表示正则表达式匹配规则。replacement
表示重定向后的内容。flag
表示 rewrite 支持的标志位。
3.1 rewrite 跳转实现
使用 rewrite 可以对 URL 进行重定向或重写,常用于实现网站 URL 的美化、重定向等功能。
Nginx 通过 ngx_http_rewrite_module 模块支持 URL 重写,它也支持 if 条件判断,但不支持 else。在进行跳转时,从一个 location 跳转到另一个 location,但最多只能执行 10 次跳转,否则 Nginx 将返回 500 错误。使用 PCRE 语法规则进行匹配,并通过重写模块的 set 指令创建新的变量并设置其值。
3.2 rewrite 执行顺序
rewrite 指令按照配置文件中的先后顺序执行,匹配成功后会立即执行相应的重定向或重写操作。
- 执行 server 块内的 rewrite 指令。
- 进行 location 匹配。
- 在选定的 location 中执行 rewrite 指令。
3.3 flag 标记说明
last
:本条规则匹配完成后,继续向下匹配新的 location URL 规则,一般用于 server 和 if 块中。break
:本条规则匹配完成后立即终止,不再匹配后续的任何规则,一般用于 location 块中。redirect
:返回 302 临时重定向,浏览器地址栏会显示跳转后的 URL 地址。permanent
:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址。
四、rewrite 和 location 区别
rewrite 和 location 在功能上有些相似,都能实现跳转,但主要区别在于:
- rewrite 用于在同一域名内更改获取资源的路径。
- location 用于对一类路径进行访问控制或反向代理,也可以用proxy_pass将请求代理到其他机器。
五、Nginx Rewrite 示例
5.1 基于域名的跳转
现在公司旧域名www.tong.com有业务需求变更,需要使用新域名www.ctt.com代替,但是旧域名不能废除,需要跳转到新域名上,而且后面的参数保持不变。
vim /usr/local/nginx/conf/nginx.conf #编辑nginx配置文件
server {listen 80;server_name www.tong.com; #域名修改 charset utf-8;access_log /var/log/nginx/access.log; #日志修改location / {#添加域名重定向if ($host = 'www.tong.com'){ #$host为rewrite全局变量,代表请求主机头字段或主机名 rewrite ^/(.*)$ http://www.ctt.com/$1 permanent; #$1为正则匹配的内容,即“域名/”之后的字符串}root html;index index.html index.htm;}}
echo "192.168.80.20 www.tong.com www.ctt.com" >> /etc/hosts #修改本地host映射
#创建test/1.htmlcd /usr/local/nginx/htmlmkdir test #创建目录echo "测试web1" > test/1.html
systemctl restart nginx #重启nginx服务
浏览器输入模拟访问 http://www.tong.com/test/1.html(虽然这个请求内容是不存在的)
会跳转到www.ctt.com/test/1.html,查看元素可以看到返回301,实现了永久重定向跳转,而且域名后的参数也正常跳转。
5.2 基于客户端 IP 访问跳转
今天公司业务新版本上线,要求所有 IP 访问任何内容都显示一个固定维护页面,只有公司 IP :192.168.80.20访问正常。
vim /usr/local/nginx/conf/nginx.conf
server {listen 80;server_name www.tong.com; #域名修改 charset utf-8;access_log /var/log/nginx/access.log; #日志修改#设置是否合法的IP标记set $rewrite true; #设置变量$rewrite,变量值为boole值true#判断是否为合法IP#remode_addr表示客户端if ($remote_addr = "192.168.80.20"){ #当客户端IP为192.168.80.20时,将变量值设为false,不进行重写set $rewrite false;}#除了合法IP,其它都是非法IP,进行重写跳转维护页面if ($rewrite = true){ #当变量值为true时,进行重写rewrite (.+) /web.html; #将域名后边的路径重写成/web.html,例如www.tong.com/web.html}location = /web.html {root /var/www/html; #网页返回/var/www/html/web.html的内容}location / {root html;index index.html index.htm;}}
echo "页面维护中。。。" > /var/www/html/web.html
systemctl restart nginx
只有本机能跳转,其他机子直接跳转到web界面
如果rewrite (.+) /web.html; 改成rewrite (.+) /web.html permanent; 的话,如果是非 192.168.80.20
的主机访问会使浏览器修改请求访问的URL成 http://www.tong.com/web.html 再请求访问,这样就会进入
一直在 rewrite 的死循环,访问请求会一直被重写成 http://www.tong.com/web.html 再请求访问
5.3 基于旧域名跳转到新域名后面加目录
现在访问的是 http://www.tong.com/post/,现在需要将这个域名下面的访问都跳转到http://www.ctt.com/tong/post/
vim /usr/local/nginx/conf/nginx.conf
server {listen 80;server_name www.tong.com; #域名修改 charset utf-8;access_log /var/log/nginx/access.log;#添加location /post {rewrite (.+) http://www.ctt.com/tong$1 permanent; #这里的$1为位置变量,代表/post}location / {root html;index index.html index.htm;}}
mkdir -p /usr/local/nginx/html/tong/postecho "测试web4" >> /usr/local/nginx/html/tong/post/1.htmlecho "192.168.80.20 tong.com" >> /etc/hosts
systemctl restart nginx
使用浏览器访问 http://tong.com/post/1.html 跳转到 http://www.ctt.com/tong/post/1.html
5.4 基于参数匹配的跳转
现在访问http://www.tong.com/100-(100|200)-100.html 跳转到http://www.tong.com页面。
vim /usr/local/nginx/conf/nginx.conf
server {listen 80;server_name www.tong.com; #域名修改 charset utf-8;access_log /var/log/nginx/access.log;if ($request_uri ~ ^/100-(100|200)-(\d+).html$) { #\d代表匹配数字,+代表匹配1个或多个rewrite (.+) http://www.tong.com permanent;}location / {root html;index index.html index.htm;}}
systemctl restart nginx
$request_uri:包含请求参数的原始URI,不包含主机名,如:http://www.tong.com/cao/tong/index.html?a=1&b=2 中的 /cao/tong/index.php?a=1&b=2
$uri:这个变量指当前的请求URI,不包括任何参数,如:/cao/tong/index.html
$document_uri:与$uri相同,这个变量指当前的请求URI,不包括任何传递参数,如:/cao/tong/index.html
使用浏览器访问 http://www.tong.com/100-200-100.html 或 http://www.tong.com/100-100-100.html 跳转到http://www.tong.com页面。#100-200只能输入100或200
5.5 基于目录下所有 php 结尾的文件跳转
要求访问 http://www.ctt.com/upload/123.php 跳转到首页。
vim /usr/local/nginx/conf/nginx.conf
server {listen 80;server_name www.ctt.com; #域名修改 charset utf-8;access_log /var/log/nginx/access.log;location ~* /upload/.*\.php$ {rewrite (.+) http://www.ctt.com permanent;}location / {root html;index index.html index.htm;}}
systemctl restart nginx
浏览器访问 http://www.ctt.com/upload/123.php 跳转到http://www.ctt.com页面。
5.6 基于最普通一条 url 请求的跳转
要求访问一个具体的页面如 http://www.tong.com/cao/123.html 跳转到首页
vim /usr/local/nginx/conf/nginx.conf
server {listen 80;server_name www.tong.com; #域名修改 charset utf-8;access_log /var/log/nginx/www.tong.com-access.log;location ~* ^/cao/123.html {rewrite (.+) http://www.tong.com permanent;}location / {root html;index index.html index.htm;}}
systemctl restart nginx
六、总结
-
Location 指令:
location
指令用于定义请求的匹配规则以及相应的处理方式。- 可以使用不同的匹配规则来满足不同的需求,例如精确匹配、前缀匹配、正则表达式匹配等。
location
块中可以包含多个其他指令,如proxy_pass
、root
等,用于指定请求匹配时的处理逻辑。
-
Rewrite 指令:
rewrite
指令用于对请求的 URI 进行重写,实现 URL 的重定向或改写。- 可以通过简单的重写规则或者正则表达式来实现灵活的 URL 重定向。
- 使用
permanent
参数可以实现永久重定向,而不使用参数则表示临时重定向。
-
常见应用场景:
- 使用
location
指令可以根据请求的 URL 路径将请求分发到不同的处理逻辑,例如静态文件的服务、反向代理等。 - 通过
rewrite
指令可以实现 URL 的重写,将请求重定向到指定的 URL 地址,或者修改请求的 URI。
- 使用
-
注意事项:
- 在使用
rewrite
指令时,需要小心处理,避免出现重定向循环或者意外的重写结果。 - 合理设计
location
匹配规则,避免产生歧义或冲突,保证请求能够按预期进行处理。
- 在使用
总的来说,Nginx 中的 location
和 rewrite
指令为我们提供了强大的 URL 路由控制和重定向能力,能够帮助我们更好地管理 Web 服务器的请求处理流程。合理地使用这两个指令可以提升网站性能、实现灵活的请求处理逻辑。