Nginx之rewrite实现URL重写方式

 更新时间:2025年03月05日 11:19:59   作者:fkjavaer  
文章介绍了Nginx的rewrite模块,包括其重要性、相关指令(如set、if、break、return、rewrite)的使用方法和作用域,并举例说明了这些指令的实际应用场景,如域名重定向和防盗链处理

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 ~^/.*\.(jpg|jpg|gif|jfif) {
	valid_referers www.example.com;
	if ($invalid_referer){
		rewrite ^/ http://192.168.110.98/images/forbidden.jpg;
	}
	root   html;
}

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

总结

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

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 如何本地安装nginx及部署项目

    如何本地安装nginx及部署项目

    这篇文章主要介绍了如何本地安装nginx及部署项目问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • nginx搭建IPv6 ->IPv4反向代理服务器的实现

    nginx搭建IPv6 ->IPv4反向代理服务器的实现

    本文主要介绍了nginx搭建IPv6 ->IPv4反向代理服务器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • Nginx配置https原理及实现过程详解

    Nginx配置https原理及实现过程详解

    这篇文章主要介绍了Nginx配置https原理及实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Nginx轻松搞定跨域问题完整过程

    Nginx轻松搞定跨域问题完整过程

    这篇文章主要给大家介绍了关于Nginx轻松搞定跨域问题的相关资料,大家在使用nginx进行服务器管理,经常会遇到跨域问题,文中将解决方法介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • nginx禁止访问.git文件的设置教程

    nginx禁止访问.git文件的设置教程

    这篇文章主要介绍了nginx禁止访问.git文件的设置教程,.git文件会包含一份文件列表,如果你的网站是基于git协作开发的,则必须要注意这个问题,需要的朋友可以参考下
    2014-08-08
  • Nginx实现动静分离的示例代码

    Nginx实现动静分离的示例代码

    这篇文章主要介绍了Nginx实现动静分离的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Nginx限制某个IP同一时间段的访问次数和请求数示例代码

    Nginx限制某个IP同一时间段的访问次数和请求数示例代码

    nginx可以通过ngx_http_limit_conn_module和ngx_http_limit_req_module配置来限制ip在同一时间段的访问次数.具体示例代码大家参考下本文
    2017-08-08
  • Nginx可视化配置工具NginxWebUI的使用

    Nginx可视化配置工具NginxWebUI的使用

    本文主要介绍了Nginx可视化配置工具NginxWebUI的使用,可以使用 WebUI 配置 Nginx 的各项功能,包括端口转发,反向代理,ssl 证书配置,负载均衡等,感兴趣的可以了解一下
    2022-01-01
  • Nginx列出目录和文件并用密码控制访问权限配置方法

    Nginx列出目录和文件并用密码控制访问权限配置方法

    这篇文章主要介绍了Nginx列出目录和文件并用密码控制访问权限配置方法,本文给出了详细的安装配置步骤,需要的朋友可以参考下
    2015-07-07
  • nginx 作为反向代理实现负载均衡的例子

    nginx 作为反向代理实现负载均衡的例子

    以下我们就来举例说明如何使用 nginx 实现负载均衡。因为nginx在处理并发方面的优势,现在这个应用非常常见。
    2010-12-12

最新评论