NGINX的rewrite模块
4.18 Rewrite 模块
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perlcompatible regular expression),因此编译之前要安装PCRE库.
rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问,另外还可以在一定程度上提高网站的安全性。
比如: 利用rewrite 模块可以实现下面网站URL的跳转
http://www.58.com/bj --> http://beijing.58.com
4.18.1ngx_http_rewrite_module 模块指令
官方文档: https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
4.18.1.1 if 指令
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:
if (条件匹配) {
action
}
使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接:
注:$http_name
任意请求标头字段,变量名称的最后一部分是转换为小写的字段名称,用下划线替换短划线;
= #比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!= #比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~ #区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~ #区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~* #不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~* #不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f #判断请求的文件是否存在和是否不存在
-d 和 !-d #判断请求的目录是否存在和是否不存在
-x 和 !-x #判断文件是否可执行和是否不可执行
-e 和 !-e #判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)
#注意:
#如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
#nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
#官方示例
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
id=123?name=wang
取出123
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
if ($request_method = POST) {
return 405;
}请求的方法
if ($slow) {
limit_rate 10k;
}限速
if ($invalid_referer) {
return 403;
}盗链
server{
listen 443 ssl;
server_name www.ehuo.org;
ssl_certificate /apps/nginx/conf.d/ssl/www.ehuo.org.pem ;
ssl_certificate_key /apps/nginx/conf.d/ssl/www.ehuo.org.key ;
root /data/nginx/html/pc ;
location /main {
index index.html;
default_type text/html;
if ( $scheme = http ){
echo "if------> $scheme";
}
if ( $scheme = https){
echo "if ---> $scheme";
}
}
}
可以通过主机头来连接,就不用配置DNS
curl -H"host: www.ehuo.org" http://10.0.0.68/
走的是https
4.18.1.2 set 指令
指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key,另外set定义格式为set $key value,value可以是text, variables和两者的组合。
erver{
listen 443 ssl;
server_name www.ehuo.org;
ssl_certificate /apps/nginx/conf.d/ssl/www.ehuo.org.pem ;
ssl_certificate_key /apps/nginx/conf.d/ssl/www.ehuo.org.key ;
root /data/nginx/html/pc ;
default_type text/html;
location /main {
index index.html;
if ( $scheme = http ){
echo "if------> $scheme";
}
if ( $scheme = https){
echo "if ---> $scheme";
}
}
location /test {
set $name ehuo ;
echo $name ;
set $my_port $server_port;
echo $my_port ;
}
}
范例:根据网络判断是否限速
server {
.....
location /set {
set $slow 1; #如果为0,则不限速,非0限速
if ($slow) {
limit_rate 10k;
}
}
}
4.18.1.3 break 指令
用于中断当前相同作用域(location)中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位 于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令就不再执行,Nginx服务器 在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在 server块和locationif块中使用
注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模 块的指令,其它指令还会执行
location /break {
set $name ehuo ;
echo $name ;
break ; #location块中break后面指令还会执行
set $my_port $server_port ;
echo $my_port ;
echo $name ;
}
4.18.1.4 return 指令
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊 重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所 有配置都将不被执行,return可以在server、if 和 location块进行配置
语法格式:
return code; #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容,可以调用变量,其中text如果有空格,需要用单或双引号
return code URL; #返回给客户端的URL地址
return URL; #302跳转返回给客户端的URL地址,注意:URL必须是完整的URL包括scheme,如http://www.magedu.org/
范例:
拒绝特定的浏览器
location /return {
if ($http_user_agent ~* curl|wget|ApacheBench){
return 666 "user_agent";
}
}
#测试
[root@centos ~]# curl -A 'curl' www.ehuo.org/return/index.html -I
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Thu, 09 Jun 2022 10:01:46 GMT
Content-Type: text/html
Content-Length: 27
Last-Modified: Thu, 09 Jun 2022 09:58:37 GMT
Connection: keep-alive
ETag: "62a1c44d-1b"
Accept-Ranges: bytes
root@centos ~]# curl -A 'chrome' www.ehuo.org/return/
data/nginx/html/pc/return
#跳转到百度
location /return {
if ( $http_user_agent ~* curl|wget|ApacheBench|chrome|firefox){
return 301 http://www.baidu.com/;
}
}
http跳转到https
#方法1
server {
listen 80;
server_name www.ehuo.org;
return 302 https://$server_name$request_uri; #跳转到本链接
}
server {
listen 443 ssl http2;
server_name www.ehuo.org;
ssl_certificate /etc/nginx/ssl/www.ehuo.org.crt;
ssl_certificate_key /etc/nginx/ssl/www.ehuo.org.key;
location / {
root /data/www/html;
}
}
#方法2
server {
listen 80 ;
listen 443 ssl;
ssl_certificate /apps/nginx/ssl/www.wang.org.crt;
ssl_certificate_key /apps/nginx/ssl/www.wang.org.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
server_name www.wang.org ;
root /data/nginx/html/pc;
if ($scheme = http) {
return https://www.wang.org/;
}
location = /nginx_status {
stub_status;
}
}
4.18.2 rewrite 指令
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配, rewrite主要是针对用户请求的URL或者是URI做具体处理
rewrite可以配置在 server、location、if
rewrite将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI
注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的标志位用于控制此循环机制
如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301
4.18.2.1 rewrite flag 使用介绍
利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag,分别是redirect(临时 重定向302)、permanent(永久重定向301)、break和last。
其中前两种是跳转型的flag,后两种是代理型。
跳转型指由客户端浏览器重新对新地址进行请求,客户端的浏览器地址信息会发生变化,如:301,302 代理型是在WEB服务器内部实现跳转,客户端的浏览器地址信息不会发生变化,如: last,break
Syntax: rewrite regex replacement [flag]; #通过正则表达式处理用户请求并返回替换后的数据包。
Default: —
Context: server, location, if
flag说明
redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;
使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户
无标记用法:
[root@centos8 ~]#cat /apps/nginx/conf.d/www.ehuo.org.conf
server {
listen 80;
server_name www.ehuo.org;
root /data/site;
location / {
rewrite /1.html /2.html;
rewrite /2.html /3.html;
}
location /2.html {
rewrite /2.html /a.html;
}
location /3.html {
rewrite /3.html /b.html;
}
}
#准备对应代码
[root@centos8 ~]#mkdir -p /data/site
[root@centos8 ~]# echo "1.html" >/data/site/1.html
[root@centos8 ~]# echo "2.html" >/data/site/2.html
[root@centos8 ~]# echo "3.html" >/data/site/3.html
[root@centos8 ~]# echo "a.html" >/data/site/a.html
[root@centos8 ~]# echo "b.html" >/data/site/b.html
#测试结果: 当请求http://www.ehuo.org/1.html,最终将会访问/b.html
过程:/---->/1---->/2----->/3----->/3------>/b.html
4.18.2.2 break 与 last
4.18.2.2.1 break 案例
[root@centos8 ~]#cat /apps/nginx/conf.d/www.ehuo.org.conf
server {
listen 80;
server_name www.ehuo.org;
root /data/site;
location / {
rewrite /1.html /2.html break;
rewrite /2.html /3.html;
}
location /2.html {
rewrite /2.html /a.html;
}
location /3.html {
rewrite /3.html /b.html;
}
}
测试结果: 当请求/1.html,最终会访问/2.html
**原因:在location{}内部,遇到break,本location{}内以及后面的所有location{}内的所有指令都不再执行。
4.18.2.2.2 last 案例
last:对某个location的URL匹配成功后,会停止当前location的后续rewrite规则,并结束当前location, 然后将匹配生成的新URL跳转至其他location继续匹配,直到没有location可匹配后, 将最后一次location的数据返回给客户端。
last 适用于要不改变客户端访问方式但是需做多次目的URL重写的场景
root@centos8 ~]#cat /apps/nginx/conf.d/www.ehuo.org.conf
server {
listen 80;
server_name www.ehuo.org;
root /data/site;
location / {
rewrite /1.html /2.html last;
rewrite /2.html /3.html;
}
location /2.html {
rewrite /2.html /a.html;
}
location /3.html {
rewrite /3.html /b.html;
}
}
测试结果:当请求/1.html,最终会访问/a.html
原因:在location{}内部,遇到last,本location{}内后续指令不在执行;
而重写后的url会对所在的server{…}标签重新发起请求,从头到尾匹配一遍规则,哪个匹配则执行哪个。
4.18.2.2.3 break 和 last 区别
rewrite指令中的break和last都属于服务器内部跳转,客户端链接地址不变,客户端无感知 当rewrite规则遇到break指令后,本location{}后续的指令与其他location{}的所有指令都不执行。 当rewrite规则遇到last指令后,本location{}里后续规则不执行,但重写后的url会再次从头开始匹配所有Location,也包括本location,哪个location先匹配到就执行哪个,可能会造成死循环500错误
4.18.2.3 永久与临时重定向
域名的临时的调整,后期可能会变,之前的域名或者URL可能还用、或者跳转的目的域名和URL还会跳 转,这种情况浏览器不会缓存跳转,临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存。
示例: 因业务需要,将访问源域名 www.ehuo.org 的请求永久重定向到 www.huoyi.com
location / {
root /data/nginx/html/pc;
index index.html;
rewrite / http://www.huoyi.com permanent;
#rewrite / http://www.huoyi.com redirect;
}
#重启Nginx并访问域名 http://www.ehuo.org 进行测试
4.18.2.3.1 永久重定向301
域名永久型调整,即域名永远跳转至另外一个新的域名,之前的域名再也不使用,跳转记录可以缓存到 客户端浏览器
永久重定向会缓存DNS解析记录, 浏览器中有 from disk cache 信息,即使nginx服务器无法访问,浏览器也会利用缓存进行重定向
比如: 京东早期的域名 www.360buy.com 由于与360公司类似,于是后期永久重定向到了 www.jd.com
范例: permanent 301永久重定向
[root@centos8 ~]#cat /apps/nginx/conf.d/www.ehuo.org.conf
server {
listen 80;
server_name www.ehuo.com;
root /data/site;
location / {
rewrite /1.html /2.html permanent;
rewrite /2.html /3.html;
}
}
#测试结果: 当请求/1.html,最终会访问/2.html
#原因:在location{}内部遇到permanent,客户端会重新发起新请求到新的重定向地址进行访问,而且url
会修改为后面的新URL
4.18.2.3.2 临时重定向302
域名临时重定向,告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,因此浏览器 不会缓存当前域名的解析记录,而浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最大的本质区别。
即当nginx服务器无法访问时,浏览器不能利用缓存,而导致重定向失败
范例: redirect 302 临时重定向
[root@centos8 ~]#cat /apps/nginx/conf.d/www.ehuo.org.conf
server {
listen 80;
server_name www.ehuo.com;
root /data/site;
location / {
rewrite /1.html /2.html redirect ;
rewrite /2.html /3.html;
}
}
#测试结果: 当请求/1.html,最终会访问/2.html
#原因:在location{}内部遇到redirect,客户端会重新发起新请求到新的重定向地址进行访问,而且url会
修改为后面的新URL
4.18.2.3.3 redirect与permanent区别
redirect与permanent都会导致客户端上重新发起的请求,链接地址会发生变化,客户端可以感知到变化
推荐链接
发表评论