当前位置: 首页 > Linux

下面详细说说Nginx的rewrite模块

时间:2023-04-07 00:17:39 Linux

rewrite模块就是ngx_http_rewrite_module模块,主要作用是重写requestURI,是Nginx默认安装的模块。重写模块会根据PCRE正则匹配重写URI,然后发起内部跳转匹配位置,或者直接做30x重定向返回客户端。指令执行顺序先依次执行server块中的rewrite模块指令,获取rewrite后的requestURI,然后循环执行后面的指令。如果没有遇到中断循环标志,这个循环最多可以执行10次,但是我们可以在改写后使用break指令中断新一轮循环(1)。根据改写后的请求URI,匹配定义的位置块(2)。依次执行匹配位置breakContext:server,location中的rewrite模块指令,if停止执行ngx_http_rewrite_module集合的指令,其他模块指令不受影响。``服务器{听8080;#这里break会停止执行server块的return指令(return指令属于rewrite模块)#如果被注释掉,所有请求进来返回200“确定”;location=/testbreak{休息;返回200$request_uri;proxy_passhttp://127.0.0.1:8080/other;}location/{return200$request_uri;}}#发送请求如下#curl127.0.0.1:8080/testbreak#/other#可以看到返回的是/other而不是/testbreak,说明还是执行了proxy_pass指令。#也就是说不会破坏其他模块的指令#(proxy_pass是ngx_http_proxy_module的一条指令)ifContext:server,location``*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26按指定条件决定是否执行if块语句中的内容if中的几个判断条件1.变量名,如果变量$variable的值为空字符串或字符串“0”,则为false2.变量andastringCompareequalto(=)Notequalto(!=)注意这里不应该把相等当成赋值语句3.变量和正则表达式的模式匹配操作符可以是(~区分大小写的正则匹配,~_不区分大小写正则匹配,!!_,前两个不)4.使用-f(存在)和!-f(不存在)检查文件是否存在5.使用-检查路径是否存在d(存在)和!-d(不存在)后面的判断可以是字符串也可以是变量6.检查文件、路径或链接文件是否存在使用-e(存在)和!-e(不存在))后面的判断可以是字符串也可以是变量Variable7.判断文件是否为可执行文件,使用-x(可执行)和!-x(不可执行)。后面的判断可以是字符串也可以是变量。注意上面的1、2、3项必须判断为变量。4、5、6、7可以是变量也可以是字符串,-f/-d/-e/-x的基本用法和bash一致。`设置$变量“0”;if($variable){#不会执行,因为“0”是假的break;}#使用变量匹配正则表达式没有问题if($http_host~"^star.igrow.cn$"){break;}#字符串匹配正则表达式错误if("star"~"^star.igrow.cn$"){break;}#检查文件类的字符串和变量if(!-f"/data.log"){break;}if(!-f$filename){中断;}`*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23返回`上下文:服务器,本地tion,if`*1`returncode[text];returncodeURL;returnURL;`*1*2*3停止处理并将指定代码返回给客户端非标准代码444关闭连接而不发送响应报头.从0.8.42版本开始,return语句可以指定重定向url(状态码可以是:301、302、303、307),也可以指定其他状态码的响应文本内容,重定向url和响应文本可以包含变量。有一种特殊情况,重定向的url可以指定为本服务器的本地urI。这种情况下nginx会根据请求的协议$scheme、server_name_in_redirect和port_in_redirect自动生成一个完整的url(这里解释server_name_in_redirect和port_in_redirect指令是指是否使用server块中的server_name和监听端口作为重定向)`#返回码[文本];returnok到客户端location=/ok{return200"ok";}#returncodeURL;临时重定向到百度location=/redirect{return302http://www.baidu.com;}#returnURL;同上,默认为临时重定向location=/redirect{returnhttp://www.baidu.com;}`*1*2*3*4*5*6*7*8*9*10*11*12*13*14rewriteContext:server,location,if`rewriteregexreplacement[flag];`*1rewrite命令指定使用正则表达式regex来匹配请求的urI,如果匹配成功,则使用replacement来改变URI。重写指令按照它们在配置文件中出现的顺序执行。标志可用于终止指令的进一步处理。如果替换字符串替换以http://、https://或$scheme开头,则停止处理后续内容,直接重定向回客户端。第一种情况,改写后的字符串有http://`location/{#当匹配到正则表达式/test1/(.*)时,请求会暂时重定向到http://www.$1.com#相当写入flag为redirectrewrite/test1/(.*)http://www.$1.com;return200"ok";}#在浏览器中输入127.0.0.1:8080/test1/baidu#临时重定向到www.baidu.com#不会有机会执行返回指令`*1*2*3*4*5*6*7*8*9第二种情况,重写后的字符串不包含http://`location/{rewrite/test1/(.*)www.$1.com;return200"ok";}#发送请求如下#curl127.0.0.1:8080/test1/baidu#ok#没有http://所以简单重写。请求的uri从/test1/baidu改写成www.baidu.com#因为rewrite命令会顺序执行,所以下一步执行return命令,响应ok`*1*2*3*4*5*6*7*8*9*10rewrite的四个flag1.last停止处理当前的ngx_http_rewrite_module指令集,开始寻找匹配改变后的URI的位置;(因为last的英文意思是“continue”,所以会继续尝试匹配并跳转到其他位置)2.break停止处理当前ngx_http_rewrite_module指令集,就像上面提到的break指令;(break是“中断停止”)3.redirect返回302临时重定向。(可以理解为“临时出租”)4.永久退货301永久重定向。(可以理解为“搬新家”)`#如果没有rewrite,后面也没有flag,则依次执行#当可以执行的位置没有rewrite模块指令时,会rewrite并发起新一轮location匹配location/{#没有flag,默认顺序是rewrite^/test1/test2;重写^/test2/test3;#这里发起新一轮位置匹配uriis/test3}location=/test2{return200"/test2";}location=/test3{return200"/test3";}#发送如下请求#curl127.0.0.1:8080/test1#/test3`*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18last和last的区别breakLast和break是一样的,都会终止这个location中其他rewrite模块指令的执行,但是last会立即发起新一轮的location匹配,而break不会`location/{rewrite^/test1/test2;最后重写^/test2/test3;#这里发起新一轮位置匹配uri为/test3rewrite^/test3/test4;proxy_passhttp://www.baidu.com;}location=/test2{return200"/test2";}location=/test3{return200"/test3";}location=/test4{return200"/test4";}#发送如下请求#curl127.0.0.1:8080/test1#/test3当把上面的位置/改成下面的代码位置/{rewrite^/test1/测试2;#这里不会发起新一轮的位置匹配;是时,后续重写模块指令的执行将被终止。重写的uri为/more/index.htmlrewrite^/test2/more/index.htmlbreak;重写/more/index.html/test4;#这条指令会被忽略#因为proxy_pass不是rewrite模块的指令,所以不会被breakproxy_pass终止https://www.baidu.com;}#发送如下请求#浏览器输入127.0.0.1:8080/test1#代理到百度产品页面https://www.baidu.com/more/index.html;`*1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26*27*28*29*30*31*32*33*34重写后如果替换字符串替换包含新的请求参数,在后面追加之前的请求参数如果不需要之前的参数,在replacementstringreplacement的末尾打上问号,避免追加。`#因为一个?在末尾添加,rewrite后不会再追加原来的请求参数rewrite^/users/(.*)$/show?user=$1?last;`*1*2rewrite_logContext:http,server,location,是否开启或关闭rewrite模块命令的执行日志,如果开启,rewrite会将notice级别的日志记录到nginx的error_log中,默认关闭`语法:rewrite_logon|off;`*1set`Context:server,location,if`*1设置指定变量的值。变量值可以包含文本、变量或它们的组合。`location/{set$var1"hostis";设置$var2$主机;设置$var3“uri是$request_uri”;return200"responseok$var1$var2$var3";}#发送以下请求#curl127.0.0.1:8080/test#responseokhostis127.0.0.1uriis/test`*1*2*3*4*5*6*7*8*9uninitialized_variable_warnContext:http,server,location,if控制是否记录未初始化变量警告。默认启用内部实现。ngx_http_rewrite_module模块指令在配置阶段被编译成请求处理期间解释的内部指令。解释器是一个简单的虚拟堆栈机器。例如,命令location/download/{if(forbidden)return403;如果(禁止){返回403;}if(forbidden)return403;if(slow){limit_rate10k;}重写^/(download/._)/media/(._)…*$/$1/mp3/$2.mp3中断;}将被翻译成如下指令:变量$forbidden零校验return403endofcode变量$slow零校验正则表达式匹配copy“/”copy$1copy“/mp3/”copy$2copy“.mp3”end正则表达式代码结束请注意,上面的limit_rate指令没有任何指令,因为它与ngx_http_rewrite_module模块无关。为if块创建一个单独的配置。如果条件为真,将为该配置分配一个请求,limit_rate等于10k。指令重写^/(download/._)/media/(._)…*$/$1/mp3/$2.mp3break;如果正则表达式中的第一个斜杠放在括号中,则可以简化:重写^(/download/._)/media/(._)…*$$1/mp3/$2.mp3break;相应的指令将如下所示:matchofregularexpressioncopy$1copy“/mp3/”copy$2copy“.mp3”endofregularexpressionendofcodelocation(non-rewritemodule)语法在服务器块中使用,例如:服务器{位置表达式{}}