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基本操作
在 Nginx 配置中,location 主要分为三类:精确匹配、前缀匹配和正则表达式匹配。
精确匹配:指定完整的 URI 进行匹配。location = / {...}
前缀匹配:指定 URI 的前缀进行匹配。location / {...}
正则表达式匹配:使用正则表达式进行匹配。正则匹配:location ~ / {...}
location = /about {
精确匹配
}
location /blog/ {
前缀匹配
}
location ~* \.(gif|jpg|jpeg)$ {
正则表达式匹配
}
Location 常用的匹配规则
在 location 中,有一些常用的匹配规则,例如:
=: 精确匹配。也就是完全匹配
^~: 前缀匹配,如果匹配成功,停止搜索其他 location。
~ 和 ~*: 区分大小写和不区分大小写的正则表达式匹配。
!~ :区分大小写的匹配取非。!~* :不区分大小写的匹配取非。
这些匹配规则决定了如何匹配 URI,并且影响着 location 的优先级
Location 优先级
在 Nginx 中,location 的优先级遵循"先精确匹配,再前缀匹配,最后正则表达式匹配"的原则。这意味着精确匹配的 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 这样的数字结尾的请求
}
Location 匹配顺序
在 Nginx 中,location 的匹配顺序非常重要。通常情况下,应该按照从精确匹配到前缀匹配再到正则表达式匹配的顺序进行配置,以确保匹配的准确性。
三个匹配规则定义
直接匹配网站根
第一个必选规则直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网,可以是一个静态首页,也可以直接转发给后端应用服务器
对于直接匹配网站根的需求,可以使用如下配置:
location = / { # 处理根目录请求
root html;
index index.html index.htm;
}
处理静态文件请求
第二个必选规则是处理静态文件请求,这是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;
}
通用规则
第三个规则就是通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器
非静态文件请求就默认是动态请求
location / {
proxy_pass http://127.0.0.1:8080;
}
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 可以对 URL 进行重定向或重写,常用于实现网站 URL 的美化、重定向等功能。
Nginx 通过 ngx_http_rewrite_module 模块支持 URL 重写,它也支持 if 条件判断,但不支持 else。在进行跳转时,从一个 location 跳转到另一个 location,但最多只能执行 10 次跳转,否则 Nginx 将返回 500 错误。使用 PCRE 语法规则进行匹配,并通过重写模块的 set 指令创建新的变量并设置其值
rewrite 执行顺序
ewrite 指令按照配置文件中的先后顺序执行,匹配成功后会立即执行相应的重定向或重写操作。
- 执行 server 块内的 rewrite 指令。
- 进行 location 匹配。
- 在选定的 location 中执行 rewrite 指令
flag 标记说明
last:本条规则匹配完成后,继续向下匹配新的 location URL 规则,一般用于 server 和 if 块中。
break:本条规则匹配完成后立即终止,不再匹配后续的任何规则,一般用于 location 块中。
redirect:返回 302 临时重定向,浏览器地址栏会显示跳转后的 URL 地址。
permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址。
rewrite 和 location 区别
rewrite 和 location 在功能上有些相似,都能实现跳转,但主要区别在于:
- rewrite 用于在同一域名内更改获取资源的路径。
- location 用于对一类路径进行访问控制或反向代理,也可以用proxy_pass将请求代理到其他机器。
Nginx Rewrite 示例
现在公司旧域名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.html
cd /usr/local/nginx/html
mkdir test #创建目录
echo "测试web1" > test/1.html
systemctl restart nginx #重启nginx服务
浏览器输入模拟访问 http://www.tong.com/test/1.html(虽然这个请求内容是不存在的)
会跳转到www.ctt.com/test/1.html,查看元素可以看到返回301,实现了永久重定向跳转,而且域名后的参数也正常跳转。
基于客户端 IP 访问跳转
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;
}
}