Nginx之rewrite实现URL重写

news2024/11/25 7:00:46

1.开篇

rewrite是nginx服务器提供的一个重要功能,用于实现URL的重写。例如我们访问https://aa.qq.com,打开的是https://age.qq.com/,这就是使用URL重写的特性来实现的。

ngx_http_rewrite_module为实现URL重写提供了指令支持。

官方文档地址:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html

接下来我们来看看rewrite的相关指令。

2.rewrite相关指令

2.1 set指令

作用域:server, location, if

语法:set $variable value;

该指令可以设置一个变量。

$variable:为变量的名称,可以看到变量的名称以$符号开头,且不要与nginx预设的全局变量名相同。

value:为变量的值,可以是字符串、其他变量或者两者的组合。

既然自定义的变量名不能与nginx的全局变量名相同,那就有必要了解使用rewrite功能时常用的nginx全局变量。

rewrite常用全局变量

全局变量说明
$args用于获取请求中的参数。例如:http://192.168.110.92/test?name=tom&age=18,$args的值就为name=tom&age=18
$host用于获取请求中的主机部分的值。例如:http://192.168.110.92/test?name=tom&age=18,$host的值为192.168.110.92。
$http_user_agent用于获取请求中的User-Agent字段值
$remote_addr用于获取客户端的IP地址
$remote_port用于获取客户端与服务器建立连接的端口号
$request_method用于获取客户端的请求方式,例如GET、POST等
$request_uri用于获取当前请求的URI。例如:http://192.168.110.92/test?name=tom&age=18,$request_uri的值就为/test?name=tom&age=18
$query_string与$args作用相同
$scheme用于获取客户端请求使用的协议,例如http、https等
$server_addr用于获取服务端的IP地址
$server_name用于获取虚拟主机的名称
$server_port用于获取虚拟主机的监听的端口
$document_uri用于获取请求中的当前URI。例如:http://192.168.110.92/test?name=tom&age=18,$document_uri的值为/test
$uri与$document_uri作用相同
$http_user_agent用于获取请求头中User-Agent字段的值
$request_filename当前请求的文件路径

下面我们设置自定义变量,顺便体验使用一下这些全局变量。

location /test {
	default_type text/html;
	set $username zhangsan;
	return 200 <html>><p>username:$username</p><p>request_uri:$request_uri</p><p>document_uri:$document_uri</p><p>uri:$uri</p><p>query_string:$query_string</p><p>args:$args</p></html>;
}

发起请求:http://192.168.110.98/test?name=tom

2.2 if指令

作用域:server, location

语法:if (condition) { … }

如果条件表达式为true,则执行该模块大括号中的指令。

🔔Tips:if(之间有一个空格。

条件表达式有几种形式:

1)变量名,如果变量的值为空字符串或"0",则为false,其他条件为true。

if ($variable){

}

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

if ($request_method = POST){

}

3)使用正则表达式与变量的值进行匹配。变量与正则表达式之间使用~~*!~!~*,如果正则表达式包含};,则整个表达式应该用单引号或双引号括起来。

  • ~:表示匹配正则表达式,区分大小写
  • ~*:表示匹配正则表达式,不区分大小写
  • !~:表示匹配正则表达式,区分大小写,并对匹配后的结果取反
  • !~*:表示匹配正则表达式,不区分大小写,并对匹配后的结果取反
if ($http_user_agent ~ Mozilla/5.0){

}

4)判断文件是否存在:-f!-f

if (-f $request_filename){

}
if (!-f $request_filename){

}

示例:

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

我们已经在html目录下准备了一个test.html。

访问http://192.168.110.98/test.html,可以正常显示。

访问http://192.168.110.98/test,因为文件不存在,所以执行if条件块的指令。

5)判断目录是否存在:-d!-d

6)判断文件、目录或符号链接是否存在:-e!-e

7)判断文件是否可以执行:-x!-x

2.3 break指令

作用域:server, location, if;

语法:break;

在同一作用域中,中断该指令之后的其他指令,位于其前面的指令配置生效,位于其后面的指令配置则无效。

示例:如果URL中存在参数,则执行if逻辑。

location /testBreak {
	default_type text/plain;
	set $username lisi;
	if ($args){
	set $username wangwu;
		break;
		set $username zhaoliu;
	}
	add_header username $username;
	return 200 $username;
}

访问http://192.168.110.98/testBreak,指令都正常执行。

访问http://192.168.110.98/testBreak?name=zhangsan,说明执行了if逻辑。

break;语句的定义来说,在其执行后,其作用域外后面的指令应该正常执行才对,但是这里直接返回了404。这个时候,就需要我们查看error.log

在这里插入图片描述

可以发现,错误提示为文件未找到,根据错误提示,我们需要在html目录下创建一个testBreak目录,然后在testBreak目录下创建一个index.html文件

cd /usr/local/nginx
mkdir testBreak
vim index.html

<html>
    <body>this is testBreak</body>
</html>

再次访问http://192.168.110.98/testBreak?name=zhangsan,可以看到break语句执行后,其作用域外后面的指令正常执行。

2.4 return指令

作用域:server, location, if

语法:return code [text];
return code URL;
return URL;

该指令可以停止处理并指定的响应码返回给前端。既可以返回文本,也可以重定向URL。

示例:

location /testReturn {
	default_type text/plain;
	return 200 "test return";
}
location /testReturn {
	return 302 https://www.baidu.com;
}
location /testReturn {
	return https://www.baidu.com;
}

2.5 rewrite指令

在了解setifbreakreturn指令后,重头戏rewrite指令登场。

作用域:server, location, if;

语法:rewrite regex replacement [flag];

regex:用来匹配URI的正则表达式。

replacement:正则匹配成功后,用来替换URI的字符串。如果该字符串以http://https://$scheme开头,则处理将停止,并重定向URI到客户端。

flag:是一个可选参数,其有4个候选值。

flag值说明
last停止处理rewrite指令,并使用重写的URI去与各个location进行匹配
break停止处理rewrite指令,与break;效果一致
redirect如果replacement字符串不是以http://https://$scheme开头,则重定向到重写的URI,响应码为302
permanent重定向到重写的URI,响应码为301

rewrite指令通过正则表达式匹配URI,并修改URI。可同时存在多个rewrite指令,按照顺序依次对URI进行匹配和处理。

示例:

location /rewrite {
	rewrite ^/rewrite/aaa\w+$ https://www.baidu.com;
	rewrite ^/rewrite/(bbb)\w+$ /$1 last;
	rewrite ^/rewrite/(ccc)\w+$ /$1 break;
	rewrite ^/rewrite/(ddd)\w+$ /$1 redirect;
	rewrite ^/rewrite/(eee)\w+$ /$1 permanent;
}

location /bbb {
	default_type text/plain;
	return 200 "this is bbb";
}

location /ccc {
	default_type text/plain;
	return 200 "this is ccc";
}

location /ddd {
	default_type text/plain;
	return 200 "this is ddd";
}

location /eee {
	default_type text/plain;
	return 200 "this is eee";
}

2.6 rewrite_log指令

作用域:http, server, location, if

语法:rewrite_log on | off;

默认值:rewrite_log off;

该指令可以配置是否将ngx_http_rewrite_module指令的处理结果以notice级别的日志写入到error_log中。

示例:

location /rewrite {
	# 开启rewrite_log
	rewrite_log on;
	# 配置error_log
	error_log logs/error.log notice;
	rewrite ^/rewrite/aaa\w+$ https://www.baidu.com;
	rewrite ^/rewrite/(bbb)\w+$ /$1 last;
	rewrite ^/rewrite/(ccc)\w+$ /$1 break;
	rewrite ^/rewrite/(ddd)\w+$ /$1 redirect;
	rewrite ^/rewrite/(eee)\w+$ /$1 permanent;
}

这样我们就可以在error.log中看到notice级别的日志。

3.使用场景

在熟悉了ngx_http_rewrite_module的相关指令后,我们来看看rewrite的相关使用场景。

3.1 域名重定向

**场景:**公司官网上线的时候地址为www.aaa.com,随着公司的不断发展,需要将官网地址升级为www.bbb.com,但是需要在访问www.aaa.com能够自动跳转到www.bbb.com。

🔔Tips:www.aaa.com和www.bbb.com需要指向同一IP。

**解决方案:**使用rewrite指令重写URI。

server {
	listen 80;
	server_name www.aaa.com;
	rewrite ^(.*) https://www.bbb.com$1;
}

3.2 优雅处理防盗链

前面我们在【Nginx静态资源防盗链】一文中已经简单的实现了静态资源的防盗链,但是展示在页面的是一个裂开的小图片,不够美观。

我们可以如下配置:

location ~^/.*\.(png|jpg|gif|jfif) {
	valid_referers www.example.com;
	if ($invalid_referer){
		rewrite ^/ http://192.168.110.98/images/forbidden.png;
	}
	root   html;
}

如果出现盗链的情况,将会出现类似于如下效果:

以上就是Nginx之rewrite实现URL重写,Nginx是多模块化的,还有很多高级功能,我们后面继续探索。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/519851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT教程(终极版)

新建了一个网站 https://ai.weoknow.com/ 每天给大家更新可用的国内可用chatGPT 这是一篇姗姗来迟的ChatGPT教程。 小白对ChatGPT的介绍足以让你阅读我的文章。 如果你已经使用过ChatGPT&#xff0c;那么祝贺你发现了宝藏。未来的先进技术一定会帮助你有所收获。 前提是你可…

我的『1024』创作纪念日

记得&#xff0c;2020年07月22日我撰写了第1篇技术博客&#xff1a;《遗传算法实例解析》在这平凡的一天&#xff0c;我赋予了它不平凡的意义也许是立志成为一名专业T作者、也许是记录一段刚实践的经验但在那一刻&#xff0c;我已在创作这趟旅程中出发今天&#xff0c;是我成为…

百度蜘蛛简介

百度蜘蛛简介 工作机制百度蜘蛛的工作要素百度蜘蛛原理的应用Baiduspider对一个网站服务器造成的访问压力如何&#xff1f;Baiduspider多长时间之后会重新抓取我的网页&#xff1f; 工作机制 百度蜘蛛的构建的原理。搜索引擎构建一个调度程序&#xff0c;来调度百度蜘蛛的工作…

2023.5.13>>Eclipse+exe4j打包Java项目及获取exe所在文件的路径

Eclipseexe4j打包Java项目及获取exe所在文件的路径 1、打包exe文件1.1 打jar包1.2 打包exe2、在程序中获取exe所在路径3、遇到问题4、JDK version和class file version(Class编译版本号)对应关系5、参考文章 1、打包exe文件 1.1 打jar包 右单击项目选择“Export…” 1.2…

软考A计划-真题-分类精讲汇总-第三章(数据库)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

小程序开发中的插件、组件、控件到底有什么区别?

小程序插件代码由一些自定义组件和 JS 代码文件构成&#xff0c;插件开发者在发布插件时&#xff0c;这些代码被上传到后台保存起来。当小程序使用插件时&#xff0c;使用者需填写插件的 AppID 和版本号&#xff0c;就可从后台获取相应的插件代码。小程序代码编译时&#xff0c…

基于 CentOS 7 构建 LVS-DR 群集

如有错误&#xff0c;敬请谅解&#xff01; 此文章仅为本人学习笔记&#xff0c;仅供参考&#xff0c;如有冒犯&#xff0c;请联系作者删除&#xff01;&#xff01; 前言&#xff1a; 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式其各自的优势 DR 模式 原理&#xff1a;首先…

Hadoop之block切片

切片是一个逻辑概念 在不改变现在数据存储的情况下&#xff0c;可以控制参与计算的节点数目 通过切片大小可以达到控制计算节点数量的目的 有多少个切片就会执行多少个Map任务 hdfs上数据存储的一个单元,同一个文件中块的大小都是相同的 因为数据存储到HDFS上不可变&#xff0…

Qt--QString字符串类、QTimer定时器类

目录 1. QString 字符串类 dialog.cpp 2. 容器类 2.1 顺序容器 QList 示例代码&#xff1a; student.h student.cpp dialog.h dialog.cpp 运行结果&#xff1a; 2.2 关联容器 QMap 示例代码&#xff1a; dialog.h dialog.cpp 运行结果&#xff1a; 3. Qt类型 3.1 跨平台数据类型…

中断相关内容大全

中断基本概念&#xff1a;程序中断指计算机执行现行程序过程中&#xff0c;出现某种急需处理的异常情况或特殊请求&#xff0c;CPU暂时中止现行程序&#xff0c;而转去对这些异常情况或特殊请求进行处理&#xff0c;处理完毕后CPU又自动返回到现行程序的断点处&#xff0c;继续…

【刷题之路】LeetCode24——详解两两交换链表中的结点的细节

一、题目描述 原题链接&#xff1a;https://leetcode.cn/problems/swap-nodes-in-pairs/comments/ 题目描述&#xff1a;给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&am…

linux下将结果保存为图片,因为服务器是命令行界面,无法弹出窗口

解决方法来自GitHub&#xff1a;https://github.com/open-mmlab/mmdetection/issues/1405 The code below can show and save image with result. import mmcv import cv2 from mmcv.runner import load_checkpoint from mmdet.models import build_detector from mmdet.apis i…

C语言结构体位域

目录 一、C语言位域是什么&#xff1f; 二、位域详解 定义格式&#xff1a; 1. 数据类型排序改变&#xff0c;位域长度不变 2. 数据类型排序不变&#xff0c;位域长度改变 3.根据以上代码的验证可以得出以下计算位域结构体数据的方法: 三.位域的结构体数据如何进行print…

感恩有你:毕业论文致谢部分写作指南

现在正值毕业论文写作最后收尾阶段&#xff0c;估计很多同学开始各处收集如何写致谢这个部分。之前写过一篇文章中引用一位导师的“抱怨”&#xff0c;文章题目为“211导师深夜含泪发文&#xff1a;在你长达5万字的毕业论文中&#xff0c;我最欣赏致谢部分”&#xff0c;所以为…

Java面试题spring

Spring 1、不同版本的 Spring Framework 有哪些主要功能&#xff1f; 2、什么是 Spring Framework&#xff1f; Spring 是一个开源应用框架&#xff0c;旨在降低应用程序开发的复杂度。它是轻量级、松散耦合的。 它具有分层体系结构&#xff0c;允许用户选择组件&#xff0c…

国考省考行测:资料分析题,年均增长量

国考省考行测&#xff1a;资料分析题&#xff0c;年均增长量 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申…

Docker基础篇

1、为什么Docker比VM快 2、帮助启动类命令 启动类命令 启动docker&#xff1a; systemctl start docker停止Docker&#xff1a; systemctl stop docker重启Docker&#xff1a; systemctl restart docker查看状态&#xff1a; systemctl status docker设置开机自启&#x…

stable diffusion webui 教程:安装与入门

stable diffusion webui 安装与入门 一、源码仓库二、模型库地址三、在 Windows 上自动安装步骤安装Python安装git下载源代码编辑 webui-user.bat 四、如何打开五、依据文字生成图片六、API在哪里&#xff1f;七、用python调用API接口示例八、如何制作生成精美的图片1、下载模型…

Qt--多窗口编程

目录 1. QMessageBox 消息对话框&#xff08;掌握&#xff09; 示例代码&#xff1a; dialog.h dialog.cpp dialog.ui 运行结果&#xff1a; 2. 窗口类继承关系 dialog.cpp 3. QMainWindow 主窗口类 3.1 QMenuBar 菜单栏 3.2 QToolBar 工具栏 3.3 QWidget 中心组件 3.4 QStatu…

外强中干——双向带头循环链表

前言&#xff1a;众所周知&#xff0c;链表有八种结构&#xff0c;由单向或双向&#xff0c;有头或无头&#xff0c;循环或不循环构成。在本篇&#xff0c;将介绍8种链表结构中最复杂的——双向带头循环链表。听着名字或许挺唬人的&#xff0c;但实际上双向带头循环链表实现起来…