[code.nginx] Rewrite的使用

ngx_http_rewrite_module是Nginx服务器的重要模块之一,它一方面实现了URL的重写功能,另一方面为Nginx服务器提供反向代理服务提供了支持,同时,我们可以利用URL重写功能完成一些其他工作,达到特殊的效果。

域名跳转

通过Rewrite功能可以实现一级域名跳转,也可以实现多节域名跳转。在server块中配置Rewrite功能即可。
下面是几个例子:


    #  例1
    ...
    server
    {
          listen 80;
          server_name  jump.myweb.name;
          rewrite  ^/  http://jump.myweb.info;
          ...
    }
    ...

    #  例2
    ...
    server
    {
          listen 80;
          server_name  jump.myweb.name  jump.myweb.info;
          if ($host  ~  myweb\.info)  #注意正则表达式中对点号“.”要用“\”进行转义
          {
                rewrite ^(.*)  http://jump.myweb.name$1 permanent;  #多域名跳转
          }
          ...
    }
    ...
    
    #例3
    ...
    server
    {
          listen 80;
          server_name  jump1.myweb.name  jump2.myweb.name;
          if ($http_host  ~*  ^(.*)\.myweb\.name$)
          {  
                rewrite  ^(.*)  http://jump.myweb.name$1;    #  三级域名跳转
                break;
          }      
          ... #其他配置
    }
    ... #其他配置
    

在上面的例子中展示了通过Rewrite功能完成域名跳转的相关配置。
在例1中,客户端访问http://jump.myweb.name时,URL将被Nginx服务器重写为http://jump.myweb.info,客户端得到的数据其实是由http://jump.myweb.info响应的。
在例2中,客户端访问http://jump.myweb.info/reqsource时,URL将被Nginx服务器重写为http://jump.myweb.name/reqsource,客户端得到的数据实际上是由http://jump.myweb.name响应的。
在例3中,客户端访问http://jump1.myweb.name/reqsource或者http://jump2.myweb.name/reqsource,URL都将被Nginx服务器重写为http://jump.myweb.name/reqsource

域名镜像

镜像网站是指将一个完全相同的网站分别放在几个服务器上,并分别放置到几个服务器上,并分别使用独立的URL,其中一个服务器的网站叫做主站,其他的为镜像网站。镜像网站和主站没有太大区别,或者可算是主站的后备。奖项网站可以保存网页信息、历史性数据、以防止丢失。可以通过镜像网站提高网站在不同地区的响应速度。镜像网站可以平衡网站的流量负载,可以解决网络宽带限制、封锁等。
使用Nginx服务器的Rewrite功能可以轻松的实现域名镜像的跳转。其实原理很简单,就是在server块中配置Rewrite功能,将不同的镜像URL重写到指定的URL就可以了。以下是一个供大家参考的配置示例:

      ...
      server
      {
              ...
              listen 80;
              server_name mirror1.myweb.name;
              rewrite ^(.*) http://jump1.myweb.name$1 last;
      }
      server
      {
            ...
            listen 81;
            server_name mirror2.myweb.name;
            rewrite ^(.*) http://jump2.myweb.name$1 last;
      }
      ...

如果我们不想将整个网站做镜像,只想为某一个子目录下的资源做镜像,我们可以在location块中配置Rewrite功能,原理和上面是一样。比如:

        server
        {
                  listen 80;
                  server_name jump.myweb.name;
                  location ^~ /source1
                  {
                            ...
                            rewrite ^/source1(.*) http://jump.myweb.name/websrc2$1 last;
                            break;
                  }
                  location ^~ /source2
                  {
                            ...
                            rewrite ^/source2(.*) http://jump.myweb.name/websrc2$1 last;
                            break;
                  }
                  ...
        }
        ...    #其他配置

独立域名

当一个网站包含多个板块时,可以为其中的某些板块设置独立域名。其原理和设置某个子目录镜像的原理是相同的。比如:


        server
        {
                  ...
                  listen 80;
                  server_name bbs.myweb.com;
                  rewrite ^(.*) http://www.myweb.name/bbs$1 last;
                  break;
        }
        server
        {
                 ...
                 listen 81;
                 server_name  home.myweb.name;
                 rewrite ^(.*) http://www.myweb.name/home$1  last;
                 break;
        }
        ...

目录自动添加“/”

如果网站设定了默认资源文件,那么当客户端使用URL访问时可以不加具体的资源文件名称。比如:在访问www.myweb.name站点时,应该在浏览器地址栏中输入“http://www.myweb.name/index.htm”这样的URL,如果么我们设置了www.myweb.name站点的首页为index.htm,那么直接在地址栏中输入“http://www.myweb.name”即可访问成功,“/index.htm”可以省略不写,现在大家基本上也都习惯了这种访问方式。
当时如果请求的资源文件在二级目录下,这样的习惯可能会造成无法正常访问资源。比如,在访问http://www.myweb.name/bbs/index.htm时,如果将URL省略为“http://www.myweb.name/bbs/”可以进行正常访问,但是如果将URL写为“http://www.myweb.name/bbs”,将末尾的斜杠“/”也省略了,访问就会出问题。
也就是说,Nginx服务器访问二级目录时不加斜杠“/”无法访问。但是我们不可能要求客户端始终按照我们的要求在末尾添加斜杠“/”,那么如果来解决这个问题呢?我们可以使用Rewrite功能为末尾没有斜杠“/”的URL自动添加一个斜杠“/”:

          server
          {
                    ...
                    listen 81;
                    server_name www.myweb.name;
                    location ^~ /bbs
                    {
                              ...
                              if (-d $request_filename)
                              {
                                        rewrite ^/(.*)([^/])$    http://$host/$1$2/  permanent;
                              }   
                    }
          }

在该示例中,我们使用if指令判断请求的“/bbs”是目录以后,匹配接收到的URI串,并将各部分的值截取出来重新组装,并在末尾添加斜杠“/”。注意应该使用permannent标志指名是永久重定向该URI。

目录合并

搜索引擎优化(Search Engine Optimization,SEO)是一种利用搜索引擎的搜索规则来提高目的网站在有关搜索引擎内排名的方式。我们在创建自己的站点时,我们通过一些措施有效提高搜索引擎优化的程度,比如为网页添加包含有有效关键字的标题,在正文中多使用有效关键字,制作网站导航时注意通用规则,尽量避免大量的动态网页,等等。目录合并也是增强SEO的一个方法,它主要将多级目录下的资源文件请求转化为看上去是对目录级数很少的资源的访问。我们来看一个例子,比如在网站中有这样的一个网页,它的路径如下所示:

      [root]/server/12/34/56/78/9.htm

网页9.htm存在于第5级目录下,如果要访问这个资源文件,客户端的URL要写成http://www.myweb.name/server/12/34/56/78/9.htm,这非常不利于搜索引擎的搜索,同时也给客户端的输入带来负担。那么,我们有没有办法让URL的目录级数“看上去”少一写呢?通过Rewrite功能,我们很容易就可以办到。比如我们进行以下的配置:

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

那么,客户端只要输入“http://www.myweb.name/server-12-34-56-78-9.htm”即可访问到9.htm这个资源文件了。这个URL是不是“看上去”简单多了呢?这其实是充分利用了Rewrite指令支持正则表达式的特性。

防盗链

盗链是一种损害原有网站合法利益,给原网站所在服务器造成额外负担的非法行为。要采取防盗链的措施,首先需要了解盗链的实现原理。
客户端向服务器请求资源时,为了减少网络带宽,提高响应时间,服务器一般不会一次将所有资源完整地传回给客户端。比如在请求一个网页时,首先会传回该网页的文本内容,当客户端浏览器在解析文本的过程中发现有图片存在时,会再次向服务器发起对该图片资源的请求,服务器将存储的图片资源再发送给客户端。在这个过程中,如果该服务器上只包含了网页的文本内容,并没有存放相关的图片资源,而是将图片资源连接到其他站点的服务器上确立,这就形成了盗链行为。在这种情况下,客户端请求的图片资源实际上来自于其他的服务器。很明显,盗链行为是一种对其他服务器不公平的行为。我们在搭建自己的站点时应当有意识地采取防盗链措施。
要实现防盗链,需要了解HTTP协议中的请求头部的Referer头域和采用URL的格式表示访问当前网页或者文件的源地址。通过该头域的值,我们可以检测到访问目标资源的源地址。这样,如果我们检测到Referer头域中的值并不是自己站点内的URL,就采取阻止措施,实现防盗链。但是,需要提醒大家的时,由于Referer头域中的值是可以被更改的,因此该方法不能够完全阻止所有的盗链行为。
知道了盗链行为的原理和防盗链的实现原理,我们就可以利用Nginx服务器的Rewrite功能实现防盗链了。
Nginx的配置中有一个指令valid_referers,用来获取Referer头域中的值,并且根据该值的情况给Nginx全局变量$invalid_referer赋值。如果Referer头域中没有符合valid_referers指令配置的值,$invalid_referer变量将会被赋值为1。valid_referers指令的语法结构为:

        valid_referers none | blocked | server_names | string ...;
  • none,检测Referer头域不存在的情况。
  • blocked,检测Referer头域的值被防火墙或者代理服务器删除或伪装的情况。这种情况下,该头域的值不以“http://”或者“https://”开头。
  • server_names,设置一个或多个URL,检测Referer头域的值是否是这些URL中的某个。从Nginx 0.5.33以后支持使用通配符“*”。

有了valid_referers指令和$invalid_referer变量,就能通过Rewrite功能来实现防盗链。有两种实现方案:一种是根据请求资源的资源类型,一种是根据请求目录。
根据文件类型实现防盗链的一个配置实例如下:

          server
          {
                    ...
                    listen 80;
                    server_name www.myweb.name;
                    location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$
                    {
                            ...
                            valid_referers none blocked server_names *.myweb.name;
                            if ($invalid_referer)
                            {
                                      rewrite ^/  http://www.myweb.com/images/forbidden.png;
                            }
                    }  
          }

在配置中,当有网络连接对以gif、jpg、png为后缀的图片资源,以swf、flv为后缀的媒体资源、以rar、zip为后缀的压缩存放资源发起请求时,如果检测到Referer头域中没有符合valid_referers指令配置的值,就将客户单请求的URL重写为http://www.myweb.com/images/forbidden.png,这防止了非法盗链行为。当然我们也可以不重写URL,直接返回HTTP错误状态,如403状态。
根据请求目录实现防盗链的一个配置示例如下:

        server
        {
              ...
              listen 80;
              server_name www.myweb.com
              location  /file/
             {
                  ...
                  root  /server/file/;
                  valid_referers  none  blocked  server_names  *.myweb.com;
                  if ($invalid_referer)
                  {
                          rewrite ^/  http://www.myweb.com/images/forbidden.png;
                  }
             }
        }
        ...

其原理其实和根据文件类型实现防盗链的原理是一样的,只是在location块的url变量上做了改变,对于请求服务器上[root]/server/file/目录下资源采取了防盗链措施。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容

  • 《老男孩Linux运维》笔记 隐藏Nginx软件版本号 一般来说,软件的漏洞都和版本有关。因此要尽量隐藏对访问用户...
    Zhang21阅读 3,630评论 0 28
  • Rewrite重写是基于ngx_http_rewrite_module的,在编辑重写之前,请确保安装了此模块 一、...
    奋斗live阅读 896评论 0 0
  • 1.ngnix介绍 ngnix www服务软件 俄罗斯人开发 开源 性能很高 本身是一款静态WWW软件 静态小文件...
    逗比punk阅读 2,086评论 1 6
  • nginx重写规则 nginx rewrite 正则表达式匹配 大小写匹配 ~ 为区分大小写匹配 ~* 为不区分大...
    桖辶殇阅读 5,547评论 0 2
  • Nginx简介 解决基于进程模型产生的C10K问题,请求时即使无状态连接如web服务都无法达到并发响应量级一万的现...
    魏镇坪阅读 1,993评论 0 9