nginx rewrite功能使用场景分析


Posted in Servers onMay 30, 2022

前言

大家在浏览某些网站的时候,有没有发现,当输入:www.abc.com或者www.abcd.com的时候,页面均能正常显示www.abc.com的主页内容。这就是nginx rewrite的一个使用场景。

rewrite简介

rewrite是Nginx服务器提供的一个重要基本功能,主要作用用来实现URL地址重写

rewrite功能实现依赖于pcre的支持,因此在编译安装Nginx服务器之前,需安装pcre库(nginx使用ngx_http_rewrite_module模块来解析和处理Rewrite功能的相关配置)

在真正了解rewrite的使用之前,有必要全面系统学习下rewrite相关的指令和语法使用,下面来逐一了解下吧

Rewrite规则与指令

set指令

该指令用来设置一个新的变量。

nginx rewrite功能使用场景分析

  • variable,变量名,该变量名要用"$"作为变量的第一个字符,且不能与Nginx服务器预设的全局变量同名;
  • value:变量值,可以是字符串、其他变量或者变量的组合等;

一个简单的案例

server {
    listen 8081;
    server_name localhsot;
    location /server {
            set $name zhangsan;
            set $age 19;
            default_type text/plain;
            return 200 $name=$age;
    }
}

重启nginx服务,然后浏览器访问观察下效果

nginx rewrite功能使用场景分析

下面列举了Rewrite常用全局变量

这些变量可以在使用过程中结合自身的业务灵活选择使用

变量 说明
$args 变量中存放了请求URL中的请求指令。如http://IP:8080?arg1=value1&args2=value2中 的"arg1=value1&arg2=value2",功能和$query_string一样
$http_user_agent 变量存储了用户访问服务的代理信息(如果通过浏览器访问,记录的是浏览器的相关版本信息)
$host 变量存储的是访问服务器的server_name值
$document_uri 变量存储了当前访问地址的URI。比如http://IP/server?id=10&name=zhangsan中的"/server",功能和$uri一样
$document_root 变量存储的是当前请求对应location的root值,如果未设置,默认指向Nginx自带html目录所在位置
$content_length 变量存储的是请求头中的Content-Length的值
$content_type 变量存储的是请求头中的Content-Type的值
$http_cookie 变量存储的是客户端的cookie信息,可以通过add_header Set-Cookie’cookieName=cookieValue’来添加cookie数 据
$limit_rate 变量中存储的是Nginx服务器对网络连接速率的限制,也就是Nginx配置中对limit_rate指令设置的值,默认是0,不限制
$remote_addr 变量中存储的是客户端的IP地址
$remote_port 变量中存储了客户端与服务端建立连接的端口号
$remote_user 变量中存储了客户端的用户名,需要有认证模块才能获取
$scheme 变量中存储了访问协议
$server_addr 变量中存储了服务端的地址
$server_name 变量中存储了客户端请求到达的服务器的名称
$server_port 变量中存储了客户端请求到达服务器的端口号
$server_protocol 变量中存储了客户端请求协议的版本,比如"HTTP/1.1"
$request_body_file 变量中存储了发给后端服务器的本地文件资源的名称
$request_method 变量中存储了客户端的请求方式,比如"GET","POST"等
$request_filename 变量中存储了当前请求的资源文件的路径名
$request_uri 变量中存储了当前请求的URI,并且携带请求参数,比如http://IP/server?id=10&name=zhangsan中的"/server?id=10&name=zhangsan名

我们来随机测试下几个指令的使用吧

$args

server {
    listen 8081;
    server_name localhsot;
    location /server {
            set $name zhangsan;
            set $age 19;
            default_type text/plain;
            return 200 $name=$age=$args;
    }
}

nginx rewrite功能使用场景分析

$http_user_agent

nginx rewrite功能使用场景分析

nginx rewrite功能使用场景分析

其他的指令有兴趣的同学可以自行尝试,下面使用这些指令完成一个需求

自定义日志输出格式,将请求的日志输出到自定义的日志中

具体配置如下:

log_format main '$remote_addr - $request - $status - $request_uri - $http_user_agent';
   server {
        listen 8081;
        server_name localhsot;
        location /server {
                access_log logs/access-server.log main;
                set $name zhangsan;
                set $age 19;
                default_type text/plain;
                return 200 $name=$age=$args=$http_user_agent;
        }
    }

通过这种方式,就可以实现自定义请求的相关参数输出到自定义的日志文件中

nginx rewrite功能使用场景分析

if指令

该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置

nginx rewrite功能使用场景分析

condition为判定条件,可以支持以下写法:

1)变量名称,如果变量名对应的值为空或者是0,if都判断为false,其他条件为true

if ($param) { 

}
location /testif {
                set $username 'zhangsan';
                default_type text/plain;
                if ($username){
                        return 200 success;
                }
                return 200 'params is empty';
}

nginx rewrite功能使用场景分析

2) 使用"=“和”!="比较变量和字符串是否相等,满足为true,不满足为false

if ($request_method = POST) { 
 return 405; 3
}

注意:此处和Java不一样的是字符串不需加引号

3)使用正则表达式对变量匹配

  • 匹配成功返回true,否则返回false;
  • 变量与正则表达式之间使用"“,”“,”!“,”!"来连接;
  • “~” 代表匹配正则表达式过程中区分大小写;
  • "~*"代表匹配正则表达式过程中不区分大小写;
  • "!“和”!*"刚好和上面取相反值,如果匹配上返回false,匹配不上返回true;
if ($http_user_agent ~ MSIE) {
    #$http_user_agent的值中是否包含MSIE字符串,如果包含返回 true 
}

注意:正则表达式字符串一般不需要加引号,但是如果字符串中包含"}“或者是”;"等字符时,就需要把引号加上

if ($http_user_agent ~ Safari){
                        return 200 Chrome;
  }

nginx rewrite功能使用场景分析

4)判断请求文件是否存在使用"-f"和"!-f"

  • 当使用"-f"时,如果请求的文件存在返回true,不存在返回false;
  • 当使用"!f"时,如果请求文件不存在,但该文件所在目录存在返回true,文件和目录都不存在返回false,如果文件存在返回false;
if (-f $request_filename){
    #判断请求的文件是否存在
}

if (!-f $request_filename){
    #判断请求的文件是否不存在
}

案例展示

location /file {
                root html;
                default_type text/html;
                if (!-f $request_filename){
                        return 200 '<h1>not find file</h1>';
                }
        }

当访问目录下不存在的文件时,将会看到如下的异常返回

nginx rewrite功能使用场景分析

5) 判断请求的目录是否存在使用"-d"和"!-d"

  • 当使用"-d"时,如果请求的目录存在,if返回true,如果目录不存在则返回false;
  • 当使用"!-d"时,如果请求的目录不存在但该目录的上级目录存在则返回true,该目录和它上级目录都不存在则返回false,如果请求目录存在也返回false;

6) 判断请求的目录或者文件是否存在使用"-e"和"!-e"

  • 当使用"-e",如果请求的目录或者文件存在时,if返回true,否则返回false;
  • 当使用"!-e",如果请求的文件和文件所在路径上的目录都不存在返回true,否则返回false;

7) 判断请求的文件是否可执行使用"-x"和"!-x"

  • 当使用"-x",如果请求的文件可执行,if返回true,否则返回false;
  • 当使用"!-x",如果请求文件不可执行,返回true,否则返回false; break指令

该指令用于中断当前相同作用域中的其他Nginx配置。与该指令处于同一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效

nginx rewrite功能使用场景分析

location /{
    if ($param){

        set $id $1;
        break;
        limit_rate 10k;
    }
}

案例演示

location /break {
                default_type text/plain;
                set $username MIKE;
                if ($args){
                        set $username JIM;
                        break;
                        set $username JODAN;
                }
                return 200 $username;
        }

nginx rewrite功能使用场景分析

return指令

该指令用于完成对请求的处理,直接向客户端返回响应状态代码。在return后的所有Nginx配置都是无效的

nginx rewrite功能使用场景分析

  • code,为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理;
  • text:为返回给客户端的响应体内容,支持变量的使用;
  • URL:为返回给客户端的URL地址;
location /return {
                default_type application/json;
                return 200 '{id:1,name:jike}';
        }

nginx rewrite功能使用场景分析

rewrite指令

该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理

URL和URI的区别

  • URI:统一资源标识符
  • URL:统一资源定位符

nginx rewrite功能使用场景分析

  • regex,用来匹配URI的正则表达式;
  • replacement:匹配成功后,用于替换URI中被截取内容的字符串。如果该字符串是以"http://"或者"https://"开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端;
  • flag:用来设置rewrite对URI的处理行为,可选值有如下

last break redirect permanent

last : 终止继续在本location中处理接收到的URI,并将此处重写的URI作为一个新的URI,使用各location块进行处理。该标志将重写的URI重写在server块中执行,为重写后的URI提供了转入到其他location块的机会;

break : 将此处重写的URI作为一个新的URI,在本块中继续处理,该标志重写后的地址在当前的location块中执行,不会将新的URI转向其他的location块;

redirect : 将重写后的URI返回给客户端,状态码为302,指明是临时重定向URI,主要用在replacement变量不是以 “http://”或“https://”开头的情况;

redirect : 将重写后的URI返回给客户端,状态码为302,指明是临时重定向URI,主要用在replacement变量不是以 “http://”或“https://”开头的情况;

permanent : 将重写后的URI返回给客户端,状态码为301,指明是临时重定向URI,主要用在replacement变量不是以 “http://”或“https://”开头的情况;

示例1

location /rewirte {
                rewrite ^/rewrite/url\w*$ https://www.baidu.com;
                rewrite ^/rewrite/(test)/\w*$ /$1;
                rewrite ^/rewrite/(hello)/\w*$ /$1;
        }
        location /test {
                default_type text/plain;
                return 200 "hello success";
        }

示例2

location /rewirte {
                rewrite ^/rewrite/url\w*$ https://www.baidu.com;
                rewrite ^/rewrite/(test)/\w*$ /$1 last;
                rewrite ^/rewrite/(hello)/\w*$ /$1 last;
        }
        location /test {
                default_type text/plain;
                return 200 "hello success";
        }

rewrite_log指令

该指令配置是否开启URL重写日志的输出功能

nginx rewrite功能使用场景分析

开启后,URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件汇总

location /rewirte {
				rewrite_log on;
				error_log logs/error.log notice;
                rewrite ^/rewrite/url\w*$ https://www.baidu.com;
                rewrite ^/rewrite/(test)/\w*$ /$1 last;
                rewrite ^/rewrite/(hello)/\w*$ /$1 last;
        }

一、rewrite配置域名跳转

有很多大型网站,在起步的时候,比如域名为 : www.haoyijia.com,但是域名太长所带来的问题就是不方便记忆,于是后面改成 www.hyj.com,问题是,一些老用户之前一直习惯了那个长域名,如何在老用户输入长域名的时候仍然可以跳转到新的短域名上呢?就可以考虑使用rewrite的功能;下面在本地做一下模拟。

配置步骤:

1、准备两个域名

这里我直接在本地模拟2个域名,通过在本地的hosts文件配置下就可以了

nginx rewrite功能使用场景分析

2、配置nginx.conf文件

server {

		listen 80;
		server_name www.zcy.com www.zhangcongyi.com;
		rewrite ^/ http://www.jd.com permanent;
	}

重启nginx服务,浏览器访问:www.zcy.com 或者www.zhangcongyi.com,观察效果

nginx rewrite功能使用场景分析

nginx rewrite功能使用场景分析

nginx rewrite功能使用场景分析

nginx rewrite功能使用场景分析

二、rewrite配置独立域名

一个完整的项目包含多个模块,比如购物网站有商品商品搜索模块、商品详情模块、购物车模块等,那么我们如何为每一个模块设置独立的域名。

server{
		listen 80;
		server_name search.hm.com;
		rewrite ^(.*) http://www.hm.com/bbs$1 last;
	}
	server{
		listen 81;
		server_name item.hm.com;
		rewrite ^(.*) http://www.hm.com/item$1 last;
	}
	server{
		listen 82;
		server_name cart.hm.com;
		rewrite ^(.*) http://www.hm.com/cart$1 last;
	}

本地的hosts文件添加如下配置

nginx rewrite功能使用场景分析

重启nginx服务,可以在浏览器访问下观察效果如何

nginx rewrite功能使用场景分析

三、rewrite配置目录合并

搜索引擎优化(SEO)是一种利用搜索引擎的搜索规则,来提供目的网站的有关搜索引擎内排名的方式;

我们在创建自己的站点时,可以通过很多种方式有效提供搜索引擎优化的程度,其中有一项就包含URL的目录层级一般不要超过三层,否则的话不利于搜索引擎的搜索也给客户端的输入带来了负担;

但是将所有的文件放在一个目录下又会导致文件资源管理混乱,并且访问文件的速度也会随着文件增多而慢下来,这两个问题是相互矛盾的,使用rewrite就可以解决上述问题;

举例,网站中有一个资源文件的访问路径时,比如访问:/server/11/22/33/44/20.html,也就是说20.html存在于第5级目录下,如果想要访问该资源文件,客户端的URL地址就要写成http://www.web.name/server/11/22/33/44/20.html

server {
	listen 80;
	server_name www.web.com;
	location /server{
		root html;
	}
}

nginx rewrite功能使用场景分析

nginx rewrite功能使用场景分析

但是这个是非常不利于SEO搜索引擎优化的,同时客户端也不好记,使用rewrite我们可以进行如下配置:

server {
	listen 80;
	server_name www.web.com;
	location /server{
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)- ([0-9]+)\.html$ /server/$1/$2/$3/$4/$5.html last;
	}
}

到此这篇关于nginx rewrite功能使用的文章就介绍到这了!


Tags in this post...

Servers 相关文章推荐
Nginx配置并兼容HTTP实现代码解析
Mar 31 Servers
小程序后台PHP版本部署运行 LNMP+WNMP
Apr 01 Servers
Nginx使用Lua模块实现WAF的原理解析
Sep 04 Servers
nginx实现动静分离的方法示例
Nov 07 Servers
nginx中proxy_pass各种用法详解
Nov 07 Servers
Nginx实现会话保持的两种方式
Mar 18 Servers
Tomcat用户管理的优化配置详解
Mar 31 Servers
docker-compose部署Yapi的方法
Apr 08 Servers
Linux中文件的基本属性介绍
Jun 01 Servers
详解apache编译安装httpd-2.4.54及三种风格的init程序特点和区别
Jul 15 Servers
ubuntu端向日葵键盘输入卡顿问题及解决
Dec 24 Servers
Shell中的单中括号和双中括号的用法详解
Dec 24 Servers
Nginx静态压缩和代码压缩提高访问速度详解
May 30 #Servers
Nginx 配置 HTTPS的详细过程
May 30 #Servers
关于windows server 2012 DC 环境 重启后蓝屏代码:0xc00002e2的问题
May 25 #Servers
聊聊配置 Nginx 访问与错误日志的问题
May 25 #Servers
利用nginx搭建RTMP视频点播、直播、HLS服务器
详解Nginx的超时keeplive_timeout配置步骤
May 25 #Servers
nginx 配置指令之location使用详解
May 25 #Servers
You might like
ThinkPHP通过AJAX返回JSON的两种实现方法
2014/12/18 PHP
php中header设置常见文件类型的content-type
2015/06/23 PHP
什么是PEAR?什么是PECL?PHP中两个容易混淆的概念解释
2015/07/01 PHP
php代码架构的八点注意事项
2016/01/25 PHP
PHP内存缓存功能memcached示例
2016/10/19 PHP
PHP redis实现超迷你全文检索
2017/03/04 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
2018/06/16 PHP
thinkPHP框架RBAC实现原理分析
2019/02/01 PHP
js 处理数组重复元素示例代码
2013/12/27 Javascript
在firefox和Chrome下关闭浏览器窗口无效的解决方法
2014/01/16 Javascript
JS实现控制表格内指定单元格内容对齐的方法
2015/03/30 Javascript
JavaScript中对DOM节点的访问、创建、修改、删除
2015/11/16 Javascript
Jquery插件之Fancybox丰富的弹出层效果附源码下载
2015/12/02 Javascript
Java框架SSH结合Easyui控件实现省市县三级联动示例解析
2016/06/12 Javascript
AngularJS基础 ng-cloak 指令简单示例
2016/08/01 Javascript
AngularJS常见过滤器用法实例总结
2017/07/06 Javascript
利用JavaScript实现栈的数据结构示例代码
2017/08/02 Javascript
Javascript中this关键字指向问题的测试与详解
2017/08/11 Javascript
JS+canvas画一个圆锥实例代码
2017/12/13 Javascript
Vue 开发音乐播放器之歌手页右侧快速入口功能
2018/08/08 Javascript
js jquery 获取某一元素到浏览器顶端的距离实现方法
2018/09/05 jQuery
Vue 页面状态保持页面间数据传输的一种方法(推荐)
2018/11/01 Javascript
Vue Autocomplete 自动完成功能简单示例
2019/05/25 Javascript
解决idea开发遇到javascript动态添加html元素时中文乱码的问题
2020/09/29 Javascript
vue实现选中效果
2020/10/07 Javascript
python利用socketserver实现并发套接字功能
2018/01/26 Python
win10子系统python开发环境准备及kenlm和nltk的使用教程
2019/10/14 Python
在python中计算ssim的方法(与Matlab结果一致)
2019/12/19 Python
python 图像的离散傅立叶变换实例
2020/01/02 Python
详解基于Scrapy的IP代理池搭建
2020/09/29 Python
通过Django Admin+HttpRunner1.5.6实现简易接口测试平台
2020/11/11 Python
电子商务个人自荐信
2013/12/12 职场文书
体育专业个人求职信范文
2013/12/27 职场文书
2014年最新离婚协议书范本
2014/10/11 职场文书
2016校本研修培训心得体会
2016/01/08 职场文书
MySQL数据库完全卸载的方法
2022/03/03 MySQL