Rewrite模块
现在 Nginx 已经成为很多公司作为前端反向代理服务器的首选,在实际工作中往往会 遇到很多跳转(重写 URL)的需求。比如更换域名后需要保持旧的域名能跳转到新的域名 上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。如果在后端使用的 Apache 服务器,虽然也能做跳转,规则库也很强大,但是用 Nginx 跳转效率会更高
Rewrite功能
rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。
rewrite 只能在
server {}
location {}
if {}
中,并且默认只能对域名后边的除去传递的参数外的字符串起作用
例如:京东登录账号,就是一个跳转只针对“?前域名后”重写
Rewrite跳转场景
- 可以调整用户浏览的 URL,看起来更规范,合乎开发及产品人员的需求
- 为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态 URL 地址伪装成静态地址提供服务
- 网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的 360buy.com会跳转到 jd.com
- 根据特殊变量、目录、客户端的信息进行 URL 调整等。
Rewrite跳转实现
Nginx 是通过 ngx_http_rewrite_module 模块支持 url 重写、支持 if 条件判断,但不支持 else。
另外该模块需要 PCRE 支持,应在编译 Nginx 时指定 PCRE 支持,默认已经安装。
根据相关变量重定向和选择不同的配置,从一个 location 跳转到另一个 location,不过这样 的循环最多可以执行 10 次,超过后 Nginx 将返回 500 错误。
同时,重写模块包含 set 指令,来创建新的变量并设其值,这在有些情景下非常有用的,如记录条件标识、传递参数到其他location、记录做了什么等等。
rewrite执行顺序如下:
- 执行server块里面的rewrite指令。
- 执行location 匹配。
- 执行选定的location中的rewrite指令。
语法格式
nginx
1
2
3
4
5
6
7
8
9
10 rewrite <regex> <replacement> [flag];
regex:表示正则匹配规则
replacement:表示跳转后的内容
flag:表示rewrite 支持的 flag 标记
flag 标记说明:
1. last:本条规则匹配完成后,继续向下匹配新的location URL规则,一般用在server和if中
2. break:本条规则匹配完成即终止,不再匹配后面的任何规则。一般用在location中
3. redirect:返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址,爬虫不会更新 url(因为是临时)。
4. permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址,爬虫更新 url。
基于旧域名跳转到新域名
例如现在访问的是www.xiao.com,现在需要将这个域名下面的发帖都跳转到 www.bin.com,后面的参数不变
创建目录
1 | [root@localhost /usr/local/nginx/html]# ls |
修改配置文件
1 | [root@localhost /usr/local/nginx/conf]# vim nginx.conf |



基于客户端IP访问跳转
在/var目录下创建一个站点文件
1 | [root@localhost /var]# mkdir -p www/html |

1 | ###设置是否合法的IP标识### |

这样在域名后瞎打或打错都会跳到这个错误页面中
基于参数匹配的跳转
http://www.xiao.com/(100|200)-100.html跳转到http://www.xiao.com页面
1 | [root@localhost /usr/local/nginx/conf]# vim nginx.conf |

在网页测试输入www.xiao.com/100-100-任意/html


基于旧域名跳转到新域名
比如我们用惯了一个网址,服务商想把地址改变,用户输入原来的网址,可以跳到新的地址
比如,我们访问bbs.xiao.com/post它会跳到新的地址,www.xiao.com/bbs/post
1 | [root@localhost /usr/local/nginx/conf]# vim nginx.conf |

$1为位置变量,代表/post
创建站点文件
1 | [root@localhost /usr/local/nginx/html]# mkdir -p bbs/post |
在网页输入bbs.xiao.com/post就会跳转到www.xiao.com/bbs/post
记得hosts文件要加bbs.xiao.com哦,不然解析不出来


基于目录下所有的php文件
访问任何php文件,都会返回首页

在网址输入www.xiao.com/upload/*(任何).php都会返回到首页


基于普通的一条url
这个是最简单的,就利用正则表达式,以什么开头以什么结尾,改改不管什么都会跳到主页面



正则location中希望proxy到带有uri部分的路径
https://www.e-learn.cn/topic/1707149
如果在正则表达式中使用带有proxy_pass
语句的 URI,则需要使用一个或多个变量来构建整个 URI。有关详细信息,请参阅此文档。 location
所以替代方案是 (1),从location
表达式中捕获 URI 并将其添加到proxy_pass
语句中。例如:
1 | location ~ ^/([A-Za-z0-9]+) { |
或者 (2),proxy_pass
不使用 URI 部分,并使用rewrite...break
. 例如:
1 | location ~ ^/([A-Za-z0-9]+) { |
用rewrite去除URL中的特定参数
日常服务中经常会用Nginx做一层代理转发,把Nginx当做前置机
比如,以下配置:
1 | server { |
这里的rewrite 就是为了去除URL中的/apis,实际的后端api中是没有这个参数的,但是为了做到在Nginx转发请求,前端需要加上这个参数,以便于区别
比如前端的请求地址是
1 | http://192.168.10.231/apis/user |
那么实际上经过Nginx转发后请求的地址是
1 | http://127.0.0.1:8000/user |
rewrite “^/api/(.)”/1 break,路径重写:
1 | (1)"^/api/(.)$":匹配路径的正则表达式,用了分组语法就是*(.)**,把/api/以后的所有部分当做1组; |
break:指令,常用的有2个,分别是:last、break;
1 | (1)last:重写路径结束后,将得到的路径重新进行一次路径匹配; |
使用rewrite,在if模块中结合root实现alias的效果
if模块中不允许写alias,所以我们可以用rewrite重写url + root实现alias的效果
- 先写一个单域名下多服务配置,访问aaa/bbb会打到index.html
1 | location ~ ^/aaa/$ { |
- 访问静态资源的时候,在location中根据uri来判断属于哪个服务,让我们去掉base路径,来实现alias的效果
1 | location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|mp3|wav|bmp|rtf|js|flv|swf|map|ico|svg|woff2|woff|ttf|map|json)$ { |