文章目录
引言:使用Rewrite跳转功能,实现服务端的某些业务调整,比如:将动态URL伪装成静态地址、更换域名后,将旧域名跳转到新域名上等等
一.Location概述
1.1Nginx三大模块
http
http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。
server
server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上只要运行一组Nginx进程,就可以运行多个网站。
location
location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。
1.2Location正则表达
匹配符 | 含义 |
---|---|
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的字符零次或多次 |
+ | 匹配前面的字符一次或多次 |
? | 匹配前面的字符零次或一次 |
. | 匹配除“\n”之外的任何单个字符 |
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用 |
转义字符 | 含义 |
---|---|
\d | 匹配纯数字 |
{n} | 重复 n 次 |
{n,} | 重复 n 次或更多次 |
{n,m} | 重复 n 到 m 次 |
[] | 定义匹配的字符范围 |
[a] | 匹配单个字符 a |
[a-z] | 匹配 a-z 小写字母的任意一个 |
[a-zA-Z0-9] | 匹配所有大小写字母或数字 |
() | 表达式的开始和结束位置 |
丨 | 或运算符 |
1.3Location优先级
location 大致可以分为三类:
精准匹配:location = / {…}
一般匹配:location / {…}
正则匹配:location ~ / {…}
location 常用的匹配规则:
= : 进行普通字符精确匹配,也就是完全匹配。
^~ : 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其它 location。
~ : 区分大小写的匹配。
~* : 不区分大小写的匹配。
!~ : 区分大小写的匹配取非。
!~* :不区分大小写的匹配取非。
(1)location = / {
}
=为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配
再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。若 location /abc,则即匹配/abc 、/abcd/ 同时也匹配 /abc/。
(2)location / {
}
因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
但若后面是正则表达式会和最长字符串优先匹配(最长匹配)
(3)location /documents/ {
}
匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
(4)location /documents/abc {
}
匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
(5)location ^~ /images/ {
}
匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条
(6)location ~* \.(gif|jpg|jpeg)$ {
}
匹配所有以 gif、jpg或jpeg 结尾的请求
然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则
(7)location /images/abc {
}
最长字符匹配到 /images/abc,优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在
(8)location ~ /images/abc {
}
匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条
(9)location /images/abc/1.html {
}
匹配/images/abc/1.html 文件,如果和正则location ~ /images/abc/1.html 相比,正则优先级更高
location 优先级:
首先精确匹配 =
其次前缀匹配 ^~
其次是按文件中顺序的正则匹配 或*
然后匹配不带任何修饰的前缀匹配
最后是交给 / 通用匹配
小结:
(location = 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /)
首先看 优先级:精确>前缀>正则>一般>通用
优先级相同:正则看上下顺序,上面的优先;一般匹配看长度,最长匹配的优先
精确、前缀、正则、一般 都没有匹配到,最后再看通用匹配
1.3Location匹配规则
实际生产中网站在使用中,至少有三个匹配规则定义:
第一个必选规则
直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。
可以是一个静态首页,也可以直接转发给后端应用服务器
location = / {
root html;
index index.html index.htm;
}
第二个必选规则
处理静态文件请求,这是nginx作为http服务器的强项
有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三个规则
通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器,非静态文件请求就默认是动态请求
location / {
proxy_pass http://tomcat_server;
}
二.Rewrite
2.1Rewrite概述
rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。
比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。
rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用
即: http://www.xy.com/abc/bbs/index.html?a=1&b=2 中的 /abc/bbs/index.html重写
2.2Rewrite跳转实现
Nginx:通过==ngx_http_rewrite_module ==模块支持URL重写、支持if条件判断,但不支持else
跳转:从一个location跳转到另一个location,循环最多可以执行10次,超过后nginx将返回500错误
PCRE支持:perl兼容正则表达式的语法规则匹配
重写模块 set 指令:创建新的变量并设其值
2.2.1执行顺序
(1) 执行 server 块里面的 rewrite 指令。
(2) 执行 location 匹配。
(3) 执行选定的 location 中的 rewrite 指令。
2.2.2语法格式
语法格式:rewrite [flag];
regex :表示正则匹配规则。
replacement :表示跳转后的内容。
flag :表示 rewrite 支持的 flag 标记。
flag标记说明
标记 | 描述 |
---|---|
last | 本条规则匹配完成后,继续向下匹配新的location URL规则,一般用在 server 和 if 中。 |
break | 本条规则匹配完成即终止,不再匹配后面的任何规则,一般使用在 location 中 |
redirect | 返回302临时重定向,浏览器地址会显示跳转后的URL地址 |
permanent | 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址 |
last和break比较
使用场景:
last一般写在server和if中
break一般用在location中
URL匹配:
last不终止重写后的URL匹配
break终止重写后的URL匹配
三.Rewrite跳转
3.1基于域名的跳转
需求:公司旧域名www.xy.com有业务需求变更,需要使用新域名www.xiayan.com代替,但是旧域名不能废除,需要跳转到新域名上,而且后面的参数保持不变。
编辑配置文件
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.xy.com; #域名地址
charset utf-8;
access_log /var/log/nginx/nginx.access.log; #日志文件地址
location / {
#添加域名重定向
if ($host = 'www.xy.com'){
#$host为rewrite全局变量,代表请求主机头字段或主机名
rewrite ^/(.*)$ http://www.xiayan.com/$1 permanent;
# ^/(.*)为,域名下的所有,“.”匹配任意一字符,“*”匹配前面字符0或多次
#$1为正则匹配的内容,即“域名/”之后的字符串-->(.*)
}
root html;
index index.html index.htm;
}
}
echo "192.168.48.10 www.xy.com www.xiayan.com" >> /etc/hosts
mkdir -p /var/log/nginx #创建日志目录
systemctl restart nginx
输入旧域名地址
3.2基于旧域名跳转新域名后面加目录
现在访问的是 http://bbs.xy.com/xiayan/,现在需要将这个域名下面的访问都跳转到http://www.xy.com/bbs/xiayan/
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.xy.com; #域名地址
charset utf-8;
access_log /var/log/nginx/nginx.access.log; #日志文件地址
location /xiayan {
rewrite (.+) http://www.xy.com/bbs$1 permanent;
#将bbs.xy.com/xiayan/(.+)跳转到新的域名地址;.+为一到多个字符
#$1为 /xiayan/(.+)
}
location / {
root html;
index index.html index.htm;
}
mkdir -p /usr/local/nginx/html/bbs/xiayan
登录服务器查看域名是否跳转
访问源域名/xiayan/new.html文件
成功跳转
3.3基于客户端IP跳转
需求:公司业务新版本上线,要求所有 IP 访问任何内容都显示一个固定维护页面,只有公司 IP :192.168.48.10访问正常。
编辑配置文件
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.xiayan.com;
charset utf-8;
access_log /var/log/nginx/nginx.access.log;
set $rewrite true; #设置rewrite变量值为true
if ($remote_addr = "192.168.48.10"){
#当客户端为次ip时,不进行跳转
set $rewrite false; #设置rewrite值为false
}
if ($rewrite = true){
#当rewrite值为真,则进行跳转
rewrite (.+) /test.html; #将所有地址跳转到 www.xiayan.com/text.html界面
}
location / {
root html;
index index.html index.htm;
}
cd /usr/local/nginx/html
echo "The server is being maintained" > test.html
systemctl restart nginx
使用192.168.48.10的IP主机访问域名
使用其它IP地址主机访问域名
3.4基于参数匹配跳转
现在访问http://www.xiayan.com/100-(100|200)-100.html 跳转到http://www.xiayan.com页面。
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.xiayan.com;
charset utf-8;
access_log /var/log/nginx/nginx.access.log;
if ($request_uri ~ ^/100-(100|200)-(\d+).html$) {
#$request_uri:包含请求参数的原始URI,不包含主机名
rewrite (.+) http://www.xiayan.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
systemctl restart nginx
$request_uri:包含请求参数的原始URI,不包含主机名,如:http://www.xy.com/abc/bbs/index.html?a=1&b=2 中的 /abc/bbs/index.html
$uri:这个变量指当前的请求URI,不包括任何参数,如:/abc/bbs/index.html
d o c u m e n t u r i : 与 document_uri:与 documenturi:与uri相同,这个变量指当前的请求URI,不包括任何传递参数,如:/abc/bbs/index.html
URL:就是一个具体路径/位置
URI:指的是一个拥有相同类型/特性的对象集合
使用浏览器访问 http://www.xiayan.com/100-200-58765.html 或 http://www.xiayan.com/100-100-1241.html 跳转到http://www.xiayan.com页面。
3.5基于目录下所有php结尾的文件跳转
要求访问 http://www.xiayan.com/xiayan/123.php 跳转到首页。
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.xiayan.com; #域名修改
charset utf-8;
access_log /var/log/nginx/nginx.access.log;
location ~* /xiayan/.*\.php$ {
rewrite (.+) http://www.xiayan.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
systemctl restart nginx
浏览器访问:www.xiayan.com/xiayan/任意以php结尾的连接,跳转首页
3.6基于URL请求跳转
要求访问一个具体的页面如 http://www.xiayan.com/abc/123.html 跳转到首页
vim /usr/local/nginx/conf/nginx.conf
server {
server_name www.xiayan.com; #域名修改
charset utf-8;
access_log /var/log/nginx/nginx.access.log;
location ~* ^/abc/123.html {
rewrite (.+) http://www.xiayan.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
systemctl restart nginx
浏览器访问 http://www.xiayan.com/abc/123.html 跳转到http://www.xiayan.com页面。
使用if 判断跳转
vim /usr/local/nginx/conf/nginx.conf
server {
server_name www.xiayan.com; #域名修改
charset utf-8;
access_log /var/log/nginx/nginx.access.log;
if ($request_uri ~* ^/abc/123.html) {
rewrite (.+) http://www.xiayan.com permanent;
}
location / {
root html;
index index.html index.htm;
}
}
systemctl restart nginx
四.总结
在实际生产中,要熟练掌握location的匹配优先级(location = 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /)
rewrite重写模块的使用,在实际生产中经常用到
在实际使用中loication与if 有时可以互换,支持location匹配的可以使用if判断语句进行匹配,if与location的关系,有点类似于循环中的for与while
在使用if判断语句时,记得“=”两次的空格,切if判断语句不支持else