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都会导致客户端上重新发起的请求,链接地址会发生变化,客户端可以感知到变化

推荐链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。