前言
- Nginx rewrite 主要功能是实现URL地址重写。Nginx的 rewrite 规则需要PCRE软件的支持,即通过Perl兼容正则表达式语法进行规则匹配;
- 该模块用于使用PCRE正则表达式更改请求URI,返回重定向并有条件地选择配置。
1.Rewrite介绍
1.1 Rewrite跳转场景
- URL看起来更规范、合理
- 企业会将动态URL地址伪装成静态地址提供服务
- 网址换新域名后,让旧的访问跳转到新的域名上
- 服务端某些业务调整
跳转实现,如图
1.2 Rewrite实际场景
1.2.1 Nginx跳转需求的实现方式
- 使用 rewrite进行匹配跳转
- 使用 if 匹配全局变量后跳转
- 使用 location匹配再跳转
1.2.2 rewrite放置的位置
-
rewrite放在 server{ },if{ }, location{ } 段中
-
location只对域名后面的除去传递参数外的字符起作用
1.2.3 对域名或参数字符串
- 使用if全局变量匹配
- 使用 proxy_pass反向代理
1.3 Nginx正则表达式匹配
- 常用的正则表达式元字符,如下表
字符 | 说明 |
---|---|
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的字符零次或多次 |
+ | 匹配前面的字符一次或多次 |
? | 匹配前面的字符零次或一次 |
. | 匹配除\n之外的任何单个字符 |
\d | 匹配纯数字 [0-9] |
{n} | 重复多次 |
{n,} | 重复n次或更多次 |
[c] | 匹配单个字符c |
[a-z] | 匹配a-z小写字母的任意一个 |
[a-zA-Z] | 匹配a-z小写字母或A-Z大写字母的任意一个 |
注意:使用诸如"[.\n]"之类的模式,可匹配包括”\n"在内的任意字符。
2.Rewrite命令
2.1 命令语法
rewrite <regex> <replacement> [flag];
'正则' '跳转后的内容' 'rewrite支持的flag标记'
2.2 flag标记说明
标记 | 说明 |
---|---|
last | 相当于Apache的[L]标记,表示完成rewrite |
break | 本条规则匹配完成即终止,不再匹配后面的任何规则 |
redirect | 返回302临时重定向,浏览器地址会显示跳转后的URL地址,爬虫不会更新url |
permanent | 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址,爬虫更新url |
2.3 last和break比较
last | break | |
---|---|---|
使用场景 | 一般写在server和if中 | 一般使用在location中 |
URL匹配 | 不终止重写后的url匹配 | 终止重写后的url匹配 |
3.Location介绍
3.1 location分类
- location = patt { } [精准匹配]
- location patt { } [一般匹配 ]
- location ~ patt { } [正则匹配]
3.2 正则匹配的常用表达式
标记 | 说明 |
---|---|
~ | 执行一个正则匹配,区分大小写 |
~* | 执行一个正则匹配,不区分大小写 |
!~ | 执行一个正则匹配,区分大小写不匹配 |
!~* | 执行一个正则匹配,不区分大小写不匹配 |
^~ | 普通字符匹配;使用前缀匹配。如果匹配成功,则不再匹配其他location |
= | 普通字符精准匹配。也就是完全匹配 |
@ | 定义一个命名的location,使用在内部定向时 |
3.3 location的优先级
3.3.1 location优先级
- 相同类型的表达式,字符长的会优先匹配
按优先级排列
= 类型
^~ 类型表达式
正则表达式(~和~*)类型
常规字符串匹配类型,按前缀匹配
通常匹配(/),如果没有其他匹配,任何请求都会匹配到
3.3.2 location优先级规则
- 匹配某个具体文件:
(location = 完整路径)>(location ^~完整路径)>(location ~*完整路径)>(location ~完整路径)>(location 完整路径)>(location /)
- 用目录做匹配访问某个文件:
(location = 目录)>(location ^~目录/)>(location ~ 目录)>(location ~* 目录)>(location 目录)>(location /)
3.3.3 location优先级的示例
1.精确匹配/,主机名后面不能带任何字符串
location = / {
[ configuration A ]
}
2.所有的地址都以/开头,这条规则将匹配到所有请求,但正则和最长字符串会优先匹配
location / {
[ configuration B ]
}
3.匹配任何以/documents/开头的地址,当后面正则表达式没有匹配到时,才起作用
location /documents/ {
[ configuration C ]
}
4.匹配任何以/documents/abc开头的地址,当后面正则表达式没有匹配到时,才会起作用
location ~ /documents/abc {
[ configuration D ]
}
5.以/images/开头的地址,匹配符合后,停止往下匹配
location ^~ /images/ {
[ configuration E ]
}
6.匹配所有以gif结尾的请求,/images/下的图片会被[configuration E]处理,
因为^~的优先级更高
location ~* \.(gif|jpg|jpeg)$ {
[ configuration F ]
}
7.最长字符匹配到/images/abc,优先级最低
location /images/abc {
[ configuration G ]
}
8.以/images/abc开头的,优先级次之
location ~ /images/abc {
[ configuration H ]
}
9.如果和正则~/images/abc/1.html相比,正则优先级更高
location /images/abc/1.html {
[ configuration I ]
}
3.4 Rewrite 和 location比较
-
相同点:都能实现跳转;
-
不同点:
rewrite是在同一域名内更改获取资源的路径;
location是对一类路径做控制访问或方向代理,还可以proxy_pass到其他机器。 -
rewrite会写在location里执行顺序:
执行server块里面的rewrite指令;
执行location匹配;
执行选定的location中的rewrite指令。
4.Rewrite跳转应用实例
4.1 基于域名的跳转
- 准备工作:
1)提供nginx初始化环境;
2)客户机需提前准备好域名映射的工作。
4.1.1 域名跳转实现步骤
1)配置Nginx初始化环境
[root@server ~]# systemctl stop firewalld
[root@server ~]# setenforce 0
[root@server ~]# systemctl disable firewalld
[root@server ~]# yum -y install pcre-devel zlib-devel
[root@server ~]# useradd -M -s /sbin/nologin nginx
[root@server ~]# tar zxvf nginx-1.12.2.tar.gz
[root@server ~]# cd nginx-1.12.2/
[root@server nginx-1.12.2]# ./configure --prefix=/usr/local/nginx \
--user=nginx --group=nginx --with-http_stub_status_module
[root@server nginx-1.12.2]# make && make install
[root@server nginx-1.12.2]# cd
[root@server ~]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# nginx //启动服务
[root@server ~]# netstat -anpt | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 56892/nginx: master
[root@server ~]# killall -1 nginx //安全重启
[root@server ~]# killall -3 nginx //停止服务
[root@server ~]# vi /etc/init.d/nginx //制作nginx执行脚本
#!/bin/bash
#chkconfig: 35 80 20
#description: Nginx HTTP Server
PROG="/usr/local/nginx/sbin/nginx"
PIDF="/usr/local/nginx/logs/nginx.pid"
case "$1" in
start)
$PROG
;;
stop)
kill -s QUIT $(cat $PIDF)
;;
reload)
kill -s HUP $(cat $PIDF)
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac
exit 0
[root@server ~]# chmod +x /etc/init.d/nginx
[root@server ~]# chkconfig --add nginx
[root@server ~]# chkconfig --list
[root@server ~]# ln -s /usr/local/nginx/conf/nginx.conf /etc/
2)修改默认站点配置
[root@server ~]# vi /etc/nginx
user nginx nginx; //更改用户和组
...
error_log logs/error.log info; //去掉开头的注释
...
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
.....
server {
listen 80;
server_name www.domain.com;
if ($host = 'www.domain.com')
{
rewrite ^/(.*)$ http://www.newdomain.com/$1 permanent;
}
charset utf-8;
access_log logs/www.domain.access.log main;
...
}
...//在最后的结束标记前 "}" 添加一个server模块(即添加新域名站点)
server {
listen 80;
server_name www.newdomain.com;
charset utf-8;
access_log /var/log/nginx/www.newdomain.com-access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
3)设置网页内容,并重启nginx服务
[root@server ~]# mkdir /var/log/nginx
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# systemctl stop nginx
[root@server ~]# systemctl start nginx
[root@server ~]# mkdir -p /usr/share/nginx/nginx/html
[root@server ~]# echo "this is a test web." > /usr/share/nginx/html/index.html
[root@server ~]# cat /usr/share/nginx/html/index.html
this is a test web.
4.1.2 验证结果
打开 fiddler 抓包工具,先在浏览器中访问IP地址
在fiddler抓包工具中可以看到
4.2 基于客户端IP访问的跳转
项目实例:
- 今天公司业务版本上线,所有IP访问任何内容都显示一个固定维护页面,只有公司IP(192.168.140.15)访问正常
4.2.1 项目实现步骤
1)准备环境:在基于域名跳转实现的基础上,删除域名跳转添加的模块(即添加的server模块)
2)更改主配置文件
[root@server ~]# vi /etc/nginx.conf
.....
server {
listen 80;
server_name www.domain.com;
set $rewrite true;
if ($remote_addr = "192.168.140.15") { //设置客户机的IP
set $rewrite false;
}
if ($rewrite = true) {
rewrite (.+) /maintenance.html;
}
location = /maintenance.html {
root /usr/share/nginx/html;
}
charset utf-8;
.....
}
[root@server ~]# vi /usr/share/nginx/html/maintenance.html
Website is Maintaining,Please visit later.
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# systemctl stop nginx
[root@server ~]# systemctl start nginx
4.2.2 测验结果
其他IP地址访问时:
4.3 基于旧、新域名跳转并添加目录的实现
4.3.1 项目步骤
- 在上述基于IP跳转实现的环境下,添加一个server站点服务
- 修改默认的站点配置文件
1)添加并修改配置文件
[root@server ~]# vi /etc/nginx.conf //
...
server {
listen 80;
server_name bbs.domain.com;
charset utf-8;
access_log logs/bbs.domain.access.log main;
location /post {
rewrite (.+) http://www.domain.com/bbs$1 permanent;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
.... //添加的server模块如下
server {
listen 80;
server_name www.domain.com;
charset utf-8;
access_log /var/log/nginx/www.newdomain.com-access.log main;
location / {
root html;
index index.html index.htm;
}
}
2)创建目录并编辑网页内容
[root@server ~]# cd /usr/local/nginx/html/
[root@server html]# mkdir -p bbs/post
[root@server html]# cd bbs/post
[root@server post]# vi keep.html
kepp going
3)检查语法并重启Nginx服务
[root@server post]# cd
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# systemctl stop nginx
[root@server ~]# systemctl start nginx
4)添加映射
[root@server ~]# vi /etc/hosts
192.168.140.15 www.domain.com bbs.domain.com
4.3.2 测试结果
4.4 基于参数匹配的跳转
4.4.1 实现步骤
- 删除添加的server站点,修改默认站点配置
[root@server ~]# vi /etc/nginx.conf
...
server {
listen 80;
server_name www.domain.com;
charset utf-8;
if ($request_uri ~ ^/100-(100|200)-(\d+).html$) { //设定匹配的参数
rewrite (.*) http://www.domain.com permanent;
}
access_log logs/bbs.domain.access.log main;
location / {
root html;
index index.html index.htm;
}
}
...
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# systemctl stop nginx
[root@server ~]# systemctl start nginx
4.4.2 测试结果
1)当参数匹配时跳转
2)当参数不匹配时不跳转
4.5 基于目录下所有php文件跳转
4.5.1 如何实现php的跳转
- 只需要修改默认站点配置,并重启nginx服务即可
[root@server ~]# vi /etc/nginx
...
server {
listen 80;
server_name www.domain.com;
charset utf-8;
location ~* /upload/.*\.php$ {
rewrite (.+) http://www.domain.com permanent;
}
access_log logs/www.domain.access.log main;
location / {
root html;
index index.html index.htm;
}
...
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# systemctl stop nginx
[root@server ~]# systemctl start nginx
4.5.2 验证结果
4.6 基于最普通url请求的跳转
4.6.1 项目步骤
- 只需修改站点下的默认配置,再重启nginx服务即可
[root@server ~]# vi /etc/nginx.conf
...
server {
listen 80;
server_name www.domain.com;
charset utf-8;
location ~* /1/test.html {
rewrite (.+) http://www.domain.com permanent;
}
...
[root@server ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server ~]# systemctl stop nginx
[root@server ~]# systemctl start nginx
4.6.2 验证结果