文章目录

  • 前言
  • 1.Rewrite介绍
  • 1.1 Rewrite跳转场景
  • 1.2 Rewrite实际场景
  • 1.2.1 Nginx跳转需求的实现方式
  • 1.2.2 rewrite放置的位置
  • 1.2.3 对域名或参数字符串
  • 1.3 Nginx正则表达式匹配
  • 2.Rewrite命令
  • 2.1 命令语法
  • 2.2 flag标记说明
  • 2.3 last和break比较
  • 3.Location介绍
  • 3.1 location分类
  • 3.2 正则匹配的常用表达式
  • 3.3 location的优先级
  • 3.3.1 location优先级
  • 3.3.2 location优先级规则
  • 3.3.3 location优先级的示例
  • 3.4 Rewrite 和 location比较
  • 4.Rewrite跳转应用实例
  • 4.1 基于域名的跳转
  • 4.1.1 域名跳转实现步骤
  • 4.1.2 验证结果
  • 4.2 基于客户端IP访问的跳转
  • 4.2.1 项目实现步骤
  • 4.2.2 测验结果
  • 4.3 基于旧、新域名跳转并添加目录的实现
  • 4.3.1 项目步骤
  • 4.3.2 测试结果
  • 4.4 基于参数匹配的跳转
  • 4.4.1 实现步骤
  • 4.4.2 测试结果
  • 4.5 基于目录下所有php文件跳转
  • 4.5.1 如何实现php的跳转
  • 4.5.2 验证结果
  • 4.6 基于最普通url请求的跳转
  • 4.6.1 项目步骤
  • 4.6.2 验证结果


前言

  • Nginx rewrite 主要功能是实现URL地址重写。Nginx的 rewrite 规则需要PCRE软件的支持,即通过Perl兼容正则表达式语法进行规则匹配;
  • 该模块用于使用PCRE正则表达式更改请求URI,返回重定向并有条件地选择配置。

1.Rewrite介绍

1.1 Rewrite跳转场景

  • URL看起来更规范、合理
  • 企业会将动态URL地址伪装成静态地址提供服务
  • 网址换新域名后,让旧的访问跳转到新的域名上
  • 服务端某些业务调整

跳转实现,如图

nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx跳转其他网址但是原网址不变

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)客户机需提前准备好域名映射的工作。

nginx跳转其他网址但是原网址不变 nginx地址跳转_优先级_02


nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx_03

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地址

nginx跳转其他网址但是原网址不变 nginx地址跳转_优先级_04


在fiddler抓包工具中可以看到

nginx跳转其他网址但是原网址不变 nginx地址跳转_优先级_05

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 测验结果

nginx跳转其他网址但是原网址不变 nginx地址跳转_html_06


其他IP地址访问时:

nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx跳转其他网址但是原网址不变_07

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 测试结果

nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx跳转其他网址但是原网址不变_08

nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx_09

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)当参数匹配时跳转

nginx跳转其他网址但是原网址不变 nginx地址跳转_html_10

2)当参数不匹配时不跳转

nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx跳转其他网址但是原网址不变_11

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 验证结果

nginx跳转其他网址但是原网址不变 nginx地址跳转_html_12


nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx_13

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 验证结果

nginx跳转其他网址但是原网址不变 nginx地址跳转_html_14


nginx跳转其他网址但是原网址不变 nginx地址跳转_html_15


nginx跳转其他网址但是原网址不变 nginx地址跳转_nginx_16