nginx的Rewrite规则详解

set指令

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

语法set $variable value;
默认值
位置server,location,if

variable:变量的名称,该变量名称要用"$"作为变量的第一个字符,且不能与Nginx服务器预设的全局变量同名。

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

Rewrite常用全局变量

变量说明
$args变量中存放了请求URL中的请求指令。比如http://192.168.200.133:8080?arg1=value1&arg s2=value2中的"arg1=value1&arg2=value2",功能和$query_string一样
$http_user_agent变量存储的是用户访问服务的代理信息(如果通过浏览器访问,记录的是浏览器的相关版本信息)
$host变量存储的是访问服务器的server_name值
$document_uri变量存储的是当前访问地址的URI。比如http://192.168.200.133/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_fifile变量中存储了发给后端服务器的本地文件资源的名称
$request_method变量中存储了客户端的请求方式,比如"GET","POST"等
$request_fifilename变量中存储了当前请求的资源文件的路径名
$request_uri变量中存储了当前请求的URI,并且携带请求参数,比如http://192.168.200.133/server?id=10&name=zhangsan中的"/server?id=10&name=zhangsan"

if指令

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

语法if(condition){…}
默认值
位置server,location

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

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

if ($param){

}

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

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

注意:此处和Java不太一样的地方是字符串不需要添加引号。

3.使用正则表达式对变量进行匹配,匹配成功返回true,否则返回false。变量与正则表达式之间使用"“,”“,”!“,”!"来连接。

"~"代表匹配正则表达式过程中区分大小写,

"~*"代表匹配正则表达式过程中不区分大小写

"!“和”!*"刚好和上面取相反值,如果匹配上返回false,匹配不上返回true

if ($http_user_agent ~ MSIE){ 
  #$http_user_agent的值中是否包含MSIE字符串,如果包含返回 
  true 
}

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

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

当使用"-f"时,如果请求的文件存在返回true,不存在返回false。当使用"!f"时,如果请求文件不存在,但该文件所在目录存在返回true,文件和目录都不存在返回false,如果文件存在返回false

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

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

当使用"-d"时,如果请求的目录存在,if返回true,如果目录不存在则返回false

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

6.判断请求的目录或者文件是否存在使用"-e"和"!-e"当使用"-e",如果请求的目录或者文件存在时,if返回true,否则返回false.

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

当使用"-x",如果请求的文件可执行,if返回true,否则返回false

当使用"!-x",如果请求文件不可执行,返回true,否则返回false

break指令

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

语法break;
默认值
位置server,location,if

例子:

location /{ 
  if ($param){ 
  set $id $1; 
  break; 
  limit_rate 10k; 
  } 
}  

return指令

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

语法return code [text];
return code URL;
return URL;
默认值
位置server,location,if

code:为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理

text:为返回给客户端的响应体内容,支持变量的使用

URL:为返回给客户端的URL地址

rewrite指令

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

该指令使用的模块是ngx_http_rewrite_module。

该ngx_http_rewrite_module模块用于使用PCRE正则表达式更改请求URI,返回重定向,并有条件地选择配置。

URL和URI的区别:

URI:统一资源标识符 
URL:统一资源定位符
语法rewrite regex replacement [flag];
默认值
位置server、location、if

在配置文件的server块中写,如:

server {
    rewrite 规则 定向路径 重写类型;
}

regex(规则):用来匹配URI的正则 路跨境表达式

replacement(定向路径):匹配成功后,用于替换URI中被截取内容的字符串。如果该字符串是以"http://"或者"https://"开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端。

flag(重写类型):用来设置rewrite对URI的处理行为,可选值有如下:

​ last:本条规则匹配完成后,继续向下匹配新的location URL规则;last一般写在server和if中,而break一般使用在location中。

​ break:本条规则匹配完成即终止,不再匹配后面的任何规则;

​ redirect:返回302临时重定向。浏览器地址会显示跳转新的URL地址。

​ permanent:返回301永久重定向。浏览器地址会显示跳转新的URL地址。

​ 比如,如下例子:

rewrite ^/(.*) http://www.baidu.com/$1 permanent;

说明:

rewrite 为固定关键字,表示开始进行rewrite匹配规则。
regex 为 ^/(.*)。 这是一个正则表达式,匹配完整的域名和后面的路径地址。
replacement就是 http://www.baidu.com/1这块了,其中1这块了,其中1是取regex部分()里面的内容。如果匹配成功后跳转到的URL。
flag 就是 permanent,代表永久重定向的含义,即跳转到 http://www.baidu.com/$1 地址上。

简单例子

server {
    # 访问 /last.html 的时候,页面内容重写到 /index.html 中
    rewrite /last.html /index.html last;
  
    # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配
    rewrite /break.html /index.html break;
  
    # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中
    rewrite /redirect.html /index.html redirect;
  
    # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中
    rewrite /permanent.html /index.html permanent;
  
    # 把 /html/*.html => /post/*.html ,301定向
    rewrite ^/html/(.+?).html$ /post/$1.html permanent;
  
    # 把 /search/key => /search.html?keyword=key
    rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
}

last和break的区别

因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:

  • last一般写在server和if中,而break一般使用在location中
  • last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
  • break和last都能组织继续执行后面的rewrite指令

location里一旦返回break则直接生效并停止后续的匹配location

server {
    location / {
        rewrite /last/ /q.html last;
        rewrite /break/ /q.html break;
    }
    location = /q.html {
        return 400;
    }
}
  • 访问/last/时重写到/q.html,然后使用新的uri再匹配,正好匹配到locatoin = /q.html然后返回了400
  • 访问/break时重写到/q.html,由于返回了break,则直接停止了

rewrite_log指令

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

语法rewrite_log on | off;
默认值rewrite_log off;
位置http、server、location、if

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

独立域名

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

需求:

http://search.hm.com 访问商品搜索模块 
http://item.hm.com 访问商品详情模块 
http://cart.hm.com 访问商品购物车模块
server{ 
  listen 80; 
  server_name search.abc.com; 
  rewrite ^(.*) http://www.abc.com/bbs$1 last; 
}
server{ 
  listen 81;
  server_name item.abc.com; 
  rewrite ^(.*) http://www.abc.com/item$1 last;
}
server{ 
  listen 82; 
  server_name cart.abc.com; 
  rewrite ^(.*) http://www.abc.com/cart$1 last; 
} 

目录自动添加"/"

问题描述

通过一个例子来演示下问题:

server { 
  listen 80; 
  server_name localhost; 
  location / { 
    root html; 
    index index.html; 
  } 
} 

要想访问上述资源,很简单,只需要通过http://192.168.1.100直接就能访问,地址后面不需要加/,但是如果将上述的配置修改为如下内容:

server { 
  listen 80; 
  server_name localhost; 
  location /hm { 
    root html; 
    index index.html; 
  } 
} 

这个时候,要想访问上述资源,按照上述的访问方式,我们可以通过http://192.168.1.100/hm/来访问,但是如果地址后面不加斜杠,页面就会出问题。如果不加斜杠,nginx服务器内部会自动做一个301的重定向,重定向的地址会有一个指令叫server_name_in_redirect on|off;来决定重定向的地址:

如果该指令为on 
重定向的地址为: http://server_name/目录名/; 
如果该指令为off 
重定向的地址为: http://原URL中的域名/目录名/;

所以就拿刚才的地址来说,http://192.169.1.100/hm如果不加斜杠,那么按照上述规则,如果指令server_name_in_redirect为on,则301重定向地址变为 http://localhost/hm/,如果为off,则301重定向地址变为http://192.168.1.100/hm/。后面这个是正常的,前面地址就有问题。

注意server_name_in_redirect指令在Nginx的0.8.48版本之前默认都是on,之后改成了off,所以现在我们这个版本不需要考虑这个问题,但是如果是0.8.48以前的版本并且server_name_in_redirect设置为on,我们如何通过rewrite来解决这个问题?

解决方案

我们可以使用rewrite功能为末尾没有斜杠的URL自动添加一个斜杠.

server { 
  listen 80; 
  server_name localhost; 
  server_name_in_redirect on; 
  location /hm { 
    if (-d $request_filename){ 
    rewrite ^/(.*)([^/])$ http://$host/$1$2/  permanent;
    } 
  } 
} 

合并目录

搜索引擎优化(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.name; 
  location /server{ 
    root html; 
  } 
}

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

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

这样的话,客户端只需要输入http://www.web.name/server-11-22-33-44-20.html就可以访问到20.html页面了。这里也充分利用了rewrite指令支持正则表达式的特性。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Nginx中,rewrite指令用于重写URL。在给定的配置中,rewrite指令被用于将旧域名www.test.com重定向到新域名www.tong.com。具体的配置如下所示: ``` server { listen 80; server_name test.com; rewrite ^/(.*) http://www.tong.com/$1 permanent; } ``` 这个配置中,listen指令用于监听80端口,server_name指令用于指定域名为test.com。而rewrite指令则使用正则表达式将所有请求重定向到新域名www.tong.com。其中,$1表示正则表达式中的第一个捕获组,即原始URL中的路径部分。 需要注意的是,rewrite指令是在server块中使用的,用于对特定域名或路径的请求进行重写操作。在给定的配置中,rewrite指令被用于将旧域名重定向到新域名,实现了域名的跳转。\[1\] #### 引用[.reference_title] - *1* [NginxNginx核心指令(rewrite指令、实战rewrite 、if指令、set和break指令】(六)-全面详解(学习总结---从...](https://blog.csdn.net/m0_58719994/article/details/131523370)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Nginx重写功能rewrite](https://blog.csdn.net/abjava1/article/details/127909784)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值