Nginx Rewrite
一:Nginx Rewrite 概述
1:Rewrite 跳转场景
可以调整用户浏览的 URL,看起来更规范,合乎开发及产品人员的需求。
为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态 URL 地址伪装成静态地址提供服务。
网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的 360buy.com 会跳转到 jd.com。
根据特殊变量、目录、客户端的信息进行 URL 调整等。
2:Rewrite 跳转实现
Nginx 是通过 ngx_http_rewrite_module 模块支持 url 重写、支持 if 条件判断,但不支持 else。另外该模块需要 PCRE 支持,应在编译 Nginx 时指定 PCRE 支持,默认已经安装。
3:Rewrite 实际应用场景
在实际工作的应用中,Nginx 跳转需求有三种方式可实现。可以直接用 rewrite 进行匹配跳转,也可以使用 if 匹配全局变量后跳转。另外,还可以使用 location 匹配再跳转。
二:Nginx Rewrite 基本操作
2.2:Location 分类
location 大致可以分为三类,语法如下:
location = patt {} [精准匹配]
location patt {} [一般匹配]
location ~ patt {} [正则匹配]
[root@localhost ~]# mkdir -p /var/www/html/aaa
[root@localhost ~]# mkdir -p /var/www/html/bbb
[root@localhost ~]# mkdir -p /var/www/html/ccc
[root@localhost ~]# echo "aaa">/var/www/html/aaa/aaa.html
[root@localhost ~]# echo "bbb">/var/www/html/bbb/index.html
[root@localhost ~]# echo "ccc">/var/www/html/ccc/INDEX.html
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
root /var/www/html/aaa;
index index.html aaa.html;
}
location = /index.html {
root /var/www/html/bbb;
index index.html index.htm;
}
location ~ /INDEX.html {
root /var/www/html/ccc;
index index.html index.htm INDEX.html;
}
备注:
访问到的是aaa
http://192.168.10.101/index.html
访问到的是bbb
http://192.168.10.101/INDEX.html
访问到的是ccc
2.3:Location 优先级
在 Nginx 的 location 配置中 location 的顺序没有太大关系。匹配优先级和 location 表达式的类型有关:相同类型的表达式,字符串长的会优先匹配。
以下是按优先级排列说明:
等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项。
^~类型表达式。一旦匹配成功,则不再查找其他匹配项。
正则表达式类型(~和~*)的优先级次之。
常规字符串匹配类型。按前缀匹配。
通用匹配(/),如果没有其它匹配,任何请求都会匹配到。
备注:
= 严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。
~ 区分大小写匹配(可用正则表达式)
!~区分大小写不匹配
~* 不区分大小写匹配(可用正则表达式)
!~*不区分大小写不匹配
^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。
很多情况下 rewrite 也会写在 location 里,它们的执行顺序如下:
(1) 执行 server 块里面的 rewrite 指令。
(2) 执行 location 匹配。
(3) 执行选定的 location 中的 rewrite 指令。
精确匹配 / ,主机名后面不能带任何字符串
location = / {
[ configuration A ]
}
因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求,但是正则和最长字符串会优先匹配
location / {
[ configuration B ]
}
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续向下搜索,只有后面的正则表达式没有匹配到时,这一条才会起作用
location /documents/ {
[ configuration C ]
}
匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续向下搜索,只有后面的正则表
达式没有匹配到时,这一条才会起作用
location ~ /documents/abc {
[ configuration D ]
}
匹配任何以 /images/ 开头的地址,匹配符合以后,停止向下匹配
location ^~ /images/ {
[ configuration E ]
}
匹配所有以 gif,jpg 或 jpeg 结尾的请求,然而所有请求/images/下的图片会被 [ configuration E] 处理,因为^~的优先级更高
location ~* \.(gif|jpg|jpeg)$ {
[ configuration F ]
}
最长字符匹配到 /images/abc,优先级最低
location /images/abc {
[ configuration G ]
}
匹配以/images/abc 开头的,优先级次之
location ~ /images/abc {
[ configuration H ]
}
匹配/images/abc/1.html 文件,如果和正则~ /images/abc/1.html 相比,正则优先级更高
location /images/abc/1.html {
[ configuration I ]
}
总结:
如果是匹配某个具体文件
(location = 完整路径) > (location ^~ 完整路径) > (location ~* 完整路径)> (location ~ 完整路径) > (location 完整路径) > (location /)
如果是用目录做匹配访问某个文件
(location = 目录) > (location ^~ 目录/) > (location ~ 目录)> (location ~* 目录) > (location 目录) > (location /)
2.4:Rewrite 常见示例
1:案例环境
192.168.10.101 www.benet.com
192.168.10.102 www.accp.com
设置好客户端和服务器端的hosts文件
要求:访问www.benet.com,跳转到www.accp.com
2:修改 Nginx 默认站点配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.benet.com;
charset utf-8;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
3:Rewrite 示例
(1)基于域名的跳转
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.benet.com;
charset utf-8;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
if ($host = 'www.benet.com')
{
rewrite ^/(.*)$ http://www.accp.com/$1 permanent;
}
}
}
备注:
$host = 'www.benet.com' 判断获取到得请求URL是否为www.benet.com 另外,=号两边有空格
permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址,爬虫更新 url,没有则返回302。
^/(.*)$
^ 指的是以任何字符或字符串开始的域名都会匹配上
/ 指得是url后跟的/,比如www.benet.com/index.html
.* 匹配任意多个字符,注意这里的(),括号里的内容会用后面的$1调用
$ 结尾
备注:
Rewrite 语法
rewrite<regex><replacement>[flag];
flag 标记说明:
last:相当于 Apache 的[L]标记,表示完成 rewrite。
break:本条规则匹配完成即终止,不再匹配后面的任何规则。
redirect:返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址,爬虫不会更新url(因为是临时)。
permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址,爬虫更新 url。
[root@localhost ~]# systemctl restart nginx
a:域名直接跳转
按 F12 可以清楚的看到从旧域名 www.benet.com 跳转到了新域名 www.accp.com 上,状态码是 301 永久重定向
b:域名后面加参数跳转
备注:
常见的正则表达式元字符
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的字符零次或多次。如"ol*"能匹配"o"及"ol"、"oll |
+ | 匹配前面的字符一次或多次。如"ol+"能匹配"ol"及"oll,但不能匹配 o |
? | 匹配前面的字符零次或一次,例如"do(es)?"能匹配"do"或者"does","?"等效于"{0,y} |
. | 匹配除"n"之外的任何单个字符,若要匹配包括"n"在内的任意字符,请使用诸如"[.\n]"之类的模式 |
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如"\n"匹配一个换行符,而"\$"则匹配"$" |
\d | 匹配纯数字 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
[c] | 匹配单个字符c |
[a-z] | 匹配 a-z小写字母的任意一个 |
[a-zA-Z] | 匹配 a-z小写字母或A-Z大写字母的任意一个 |
备注:
匹配规则
~:表示执行一个正则匹配,区分大小写。
~*:表示执行一个正则匹配,不区分大小写。
!~:表示执行一个正则匹配,区分大小写不匹配。
!~*:表示执行一个正则匹配,不区分大小写不匹配。
^~:表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他 location。
=:进行普通字符精确匹配,也就是完全匹配。
@:它定义一个命名的 location,使用在内部定向时,例如 error_page, try_files。
(2)基于客户端 IP 访问跳转
要求所有外部IP访问任何内容都显示一个固定维护页面,只有公司内部IP 访问正常
假设内部IP为192.168.10.103,外部IP为192.168.10.105
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.benet.com;
#access_log /var/log/nginx/host.access.log main;
set $rewrite true;
if ($remote_addr = "192.168.10.51") {
set $rewrite false;
}
if ($rewrite = true) {
rewrite (.+) /maintenance.html;
}
location / {
root html;
index index.html index.htm;
# if ($host = 'www.benet.com')
# {
# rewrite ^/(.*)$ http://www.accp.com/$1 permanent;
# }
}
}
备注:
(.+) 匹配整个URL,匹配上以后,就在URL后面加上/maintenance.html
.+ 匹配任意字符1次或多次
.* 匹配任意字符0次或多次
[root@localhost ~]# systemctl restart nginx
[root@localhost ~]# echo "Website is Maintaining,Please visit later."> /usr/local/nginx/html/maintenance.html
先用客户端192.168.10.51访问,能正常访问www.benet.com,再用其他IP客户端访问,打开的是maintenance.html页面
(3)基于旧域名跳转到新域名后面加目录
访问http://bbs.benet.com/post时,需要将这个域名跳转到http://www.benet.com/bbs/post
[root@localhost html]# cd /usr/local/nginx/html/
[root@localhost html]# mkdir -p bbs/post
[root@localhost html]# cd bbs/post
[root@localhost post]# echo "i am bbs">index.html
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name bbs.benet.com;
#access_log /var/log/nginx/host.access.log main;
location /post {
rewrite (.+) http://www.benet.com/bbs$1 permanent;
}
location / {
root html;
index index.html index.htm;
}
}
[root@localhost ~]# systemctl restart nginx
客户端添加域名解析
192.168.10.101 bbs.benet.com
在客户端浏览器地址栏输入 http://bbs.benet.com/post,会跳转到http://www.benet.com/bbs/post/
备注:
如果需要将bbs.benet.com的域名重写为www.benet.com/bbs
则使用如下配置:
server {
listen 80;
server_name bbs.benet.com;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
if ($host = 'bbs.benet.com')
{
rewrite ^/(.*)$ http://www.benet.com/bbs/$1 permanent;
}
}
}
(4)基于参数匹配的跳转
在访问 http://www.benet.com/100-(100|200)-100.html 跳转到 http://www.benet.com页面
[root@localhost post]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name bbs.benet.com;
#access_log /var/log/nginx/host.access.log main;
if ($request_uri ~ ^/100-(100|200)-(\d+).html$) {
rewrite (.*) http://www.benet.com permanent;
}
location / {
root html;
index index.html index.htm;
}
备注:
\d+ 匹配任意个数字
[root@localhost ~]# systemctl restart nginx
使用浏览器访问 http://www.benet.com/100-100-100.html,会跳转到http://www.benet.com
(5)基于目录下所有 php 结尾的文件跳转
要求访问 http://www.benet.com/upload/1.php跳转到首页
[root@localhost post]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name bbs.benet.com;
#access_log /var/log/nginx/host.access.log main;
location ~* /upload/.*\.php$ {
rewrite (.+) http://www.benet.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
备注:
~* 不区分大小写
~ 区分大小写
.*\.php 一个文件的名字 名字.后缀 任意名字.php
[root@localhost ~]# systemctl restart nginx
浏览器访问 http://www.benet.com/upload/1.php会跳转到http://www.benet.com
(6)基于最普通一条 url 请求的跳转
[root@localhost post]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name bbs.benet.com
#access_log /var/log/nginx/host.access.log main;
location ~* ^/1/test.html {
rewrite (.+) http://www.benet.com permanent;
}
location / {
root html;
index index.html index.htm;
}
[root@localhost ~]# systemctl restart nginx
浏览器访问 http://www.benet.com/1/test.html 跳转到http://www.benet.com