Nginx Rewrite
引言:在Nginx发布后,成为了很多公司作为前端反向代理服务器的首选,在实际工作中往往会遇到很多跳转(重写URL)的需求;使用Rewrite跳转功能实现服务端的某些业务调整,比如:将动态URL伪装成静态地址、更换域名后,将旧域名跳转到新域名上。将nginx提供的全局变量或自己设置的变量,结合正则表达式和标记实现URL重写以及重定向。
一、Nginx Rewrite
1.Nginx Rewrite跳转场景
- URL看起来更规范、合理 (http://www/baidu.com/index.html) URL就是具体路径/位置
URI:指的是一个拥有相同 类型/特性 的对象集合;统一资源标识符
- 企业会将动态URL地址伪装成静态地址提供服务
- 网址换新域名后,让旧的访问跳转到新的域名上
- 服务端某些业务调整
2.Rewrite跳转实现
- Nginx是通过ngx_http_rewrite_module模块支持url重写、支持if条件判断,但不支持else
- 另外该模块需要PCRE支持,应在编译Nginx时指定PCRE支持,默认已安装
- 根据相关变量重定向和选择不同的配置,从一个location跳转到另一个location,不过这类的循环最懂指定10次,超过后Nginx返回500错误
- 重写模块包含set指令,来创建新的变量并设其值,这在有些情境下非常有用的,如记录条件表示、传递参数到其他location,记录做了什么
- rewrite功能就是使用Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向
location是为了匹配访问路径(URL)
if作为分支判断,并且if分支,仅支持但分支;
rewrite:对访问路径进行改写
1、改写的路径nginx服务器上配置-改写路径
2、改写的路径,在后端、其他服务器上跳转
路由最多跳转15次
3.Rewrite跳转需求的实际场景
- 使用rewrite进行匹配跳转
- 使用if匹配全局变量后跳转
- 使用location匹配再跳转
rewrite放在server{},if{},location{}段中
location只对域名后边的除去传递参数外的字符串起作用
对域名或参数字符串
使用if全局变量匹配
使用proxy_pass反向代理
4.URL和URI
URL:指一个具体路径/位置
URI:指一个拥有相同类型/特性的对象集合
location是为了匹配访问路径(URL)
if做为分支语句判断,且if分支仅支持单分支
rewrie:对访问路径进行改写大分支:
1.改写路径:在Nginx服务器上-改写路径
2、改写路径:在后端/其他服务器上-跳转
二、Nginx正则表达式
1.常用正则表达式元字符:
字符 | 说明 |
---|---|
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符穿的结束位置 |
* | 匹配前面的字符零次或多次,如"ol"能匹配"o" 、“ol” 、“oll” |
+ | 匹配前面的字符一次或多次,如"ol+“能匹配"ol” 、“oll” 、“olll”,但不能匹配"o" |
? | 匹配前面的字符零次或一次; 如 ”do(es)“能匹配"do"或者"does", “?“等效于”{0,1}” |
. | 匹配除"\n"之外的任何单个字符 使用诸如"[.n]“之类的模式,可匹配包括”\n"在内的任意字符 |
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用 |
\d | 匹配纯数字 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
[] | 定义匹配的字符范围 |
{c} | 匹配单个字符c |
[a-z] | 匹配a-z小写字母的任意一个 |
[a-zA-Z0-9] | 匹配所有大小写字母或数字 |
() | 表达式的开始和结束位置 |
| | "或"运算符 |
正则表达式为了精确匹配执行规则,提高用户体验,筛选 ;正则匹配的何意所在 location需要精确index.html; 使用正则表达式就是为了节省资源,用更少的资源解决;提高访问速度
三、Rewrite的用法
1.Rewrie命令语法
rewrite <regex> <repalcement> [flag];
正则表达式 跳转后的内容 rewriet支持的flag标记
2.flag标记说明:
标记 | 说明 |
---|---|
last | 相当于Apache的[L]标记,表示完成rewrite |
break | 本条规则匹配完成即终止,不再匹配后面的任何规则 |
redirect | 返回302临时重定向,浏览器地址会显示跳转后的URL地址,爬虫不会更新url |
permanent | 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址,爬虫更新url |
3.last和break区别
last | break | |
---|---|---|
使用场景 | 一般写在server和if中 | 一般使用再location中 |
URL匹配 | 不终止重写后的url匹配 | 终止重写后的url匹配 |
4.rewrite执行顺序
执行server块里面的rewrite指令
执行location匹配
执行选定的location中的rewrite指令
四、location
从功能看,rewrite 和 location 似乎很像,都能实现跳转,主要区别在于 rewrite 是在同一域名内更改获取资源的路径,而 location 是对一类路径做控制访问或反向代理,还可以 proxy_pass 到其他机器。
1.location匹配格式
location = patt {} [精准匹配]
location patt {} [一般匹配]
location ~patt {} [正则匹配]
2.正则匹配的常用表达式
标记 | 说明 |
---|---|
~ | 执行一个正则匹配,区分大小写 |
~* | 执行一个正则匹配,不区分大小写 |
!~ | 执行一个正则匹配,区分大小写不匹配 |
!~* | 执行一个正则匹配,不区分大小写不匹配 |
^~ | 普通字符匹配;使用前缀匹配,如果匹配成功,则不再匹配其他location |
= | 普通字符精确匹配,也就是完全匹配 |
@ | 定义一个命名的location,使用在内部定向时 |
优先级精确最高,一般其次,正则最小
3.location优先级
按优先级排列
= 类型 精确匹配
^~类型表达式 普通字符,且为前缀匹配
正则表达式(~和~*)类型 区分大小写
常规字符串匹配类型,按前缀匹配 location/patt
通用匹配(/),如果没有其它匹配,任何请求都会匹配到
越精确越优先;
例如:
匹配某个具体文件
(location=完整路径) > (location 完整路径) > (location *完整路径) >(location~完整路径) > (location完整路径) > (location /)
用目录做匹配访问某个文件
(location=目录) > (location ^ 目录/) > (location 目录 ) > (location~*目录) > (location目录)
4.rewrite和location的分别
相同点:都能实现跳转
不同点:rewrite是在同一域名内更改获取资源的路径
location是对一类路径做控制访问或反向代理,还可以proxy_pass到其他机器
rewrite会卸载location里,执行顺序
执行server块里面的rewrite指令
执行location匹配
执行选定的location中的rewrite指令
五、rewrite跳转示例
1.基于域名的跳转
当公司的旧域名www.boss.com有业务需求变更,需要使用新的域名www.zxc.com代替,但旧域名还不能废除,访问旧域名的时候需要跳转到新域名,且后面的参数不变
vim /usr/lcoal/nginx/conf/nginx.conf
server {
listen 80;
server_name www.boss.com; #修改域名,(旧的域名)
charset utf-8;
access_log /var/log/nginx/boss.com.access.log; #日志修改
location / {
if ($host = 'www.boss.com') { #$host为rewrite全局变量,代表请求主机头字段或主机名
rewrite ^/(.*)$ http://www.zxc.com/$1 permanent; #$1为正则表达式,即域名后面的 字符串 }
root html;
index index.html index.htm;
}
创建一个目录,作为域名后显示访问的信息,方便验证
mkdir test
echo "boss is qiangqiangqiang" > test/1.html
mkdir -p /var/log/nginx 创建一个日志目录
systemctl restart nginx.service 重启服务
在主机映射文件内添加一行地址映射
192.168.50.128 www.boss.com www.zxc.com
验证服务
2.基于客户端IP访问跳转
公司业务新版本上线,需求所有IP访问任何内容都显示一个固定维护页面,只有公司IP:192.168.50.128可以正常进行访问;
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.boss.com; #域名修改
charset utf-8;
access_log /var/log/nginx/boss.com.access.log; #日志修改
#设置是否合法的IP标记
set $rewrite true; #设置变量时$rewrite,变量值为boole值true为真
#if判断语句,判断是否为合法IP
if ($remote_addr = "192.168.50.128") { #当客户端IP为192.168.50.128,将变量值设为 false,不进行重写
set $rewrite false;
}
#除了合法IP,其它都是非法IP,进行重写跳转维护页面;
if ($rewrite = true){ #当变量值为true时,进行重写,
rewrite (.+) /weihu.html; #重写,在访问IP后插入/weihu.html,
例如192.168.50.158/weihu.html
}
location = /weihu.html {
root /var/www/html; #网页返回/var/www/html/weihu.html的内容
}
location / {
root html;
index index.html index.htm;
}
}
mkdir -p /var/www/html
echo "zhangsan lisi wangwu " >/var/www/html/weihu.html
cat /var/www/html/weihu.html
浏览器网页验证
只有IP地址为192.168.50.128的本机可以访问,其他IP访问会进入维护页面
3.基于旧域名跳转到新域名后面加目录
访问http://www.bbs.boss.com/post ,需要将这个域名下面的访问跳转到htttp://www.zxc.com/bbs/post/
server {
listen 80;
server_name bbs.boss.com;
charset utf-8;
access_log /var/log/nginx/boss.com.access.log;
location /post {
rewrite (.+) http://www.boss.com/bbs$1 permanent;
}
location / {
root html;
index index.html index.htm;
}
}
mkdir -p /usr/local/nginx/html/bbs/post
echo "zhende manhao" > /usr/local/nginx/html/bbs/post/1.html
cat /usr/local/nginx/html/bbs/post/1.html
验证服务
4.基于参数匹配跳转
通过访问www.boss.com/100-(100|200)-100.html 跳转到www.boss.com页面
server {
listen 80;
server_name www.boss.com;
charset utf-8;
access_log /var/log/nginx/boss.com.access.log;
if ($request_uri ~ ^/100-(100|200)-(\d+).html$) {
#request包含参数的原始URI,不包含主机名
rewrite (.+) http://www.boss.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
5.基于目录下所有php结尾的文件跳转
根据需求,访问http://www.boss.com/boss/upload.php跳转到首页
vim /usr/local/nginx/cong/nginx.conf
server {
listen 80;
server_name www.boss.com;
charset utf-8;
access_log /var/log/nginx/boss.com.access.log;
location ~* /boss/.*\.php$ {
rewrite (.+) http://www.boss.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
浏览器访问验证,只要在boss目录下任意以".php"结尾的文件都跳转到www.boss.com
6.基于一条最普通的url请求跳转
要求访问一个具体的页面,如http://www.boss.com/abc/123.html 跳转到首页
vim /usr/local/nginx/cong/nginx.conf
server {
listen 80;
server_name www.boss.com;
charset utf-8;
access_log /var/log/nginx/boss.com.access.log;
location ~* ^/abc/123.html {
rewrite (.+) http://www.boss.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
总结
在实际的生产环境,要熟练掌握location的匹配优先级(location=完整路径)>(location^~路径)>(location*正则顺序)>(location部分起始路径)>(location/)
对rewrite重写模块的使用也需要熟练掌握,location和if也可以切换使用,不固定模式