Nginx之rewrite功能

1.  什么是nginx rewrite?

       Nginx rewrite的主要功能是实现URL地址重写。

       Nginx rewrite规则需要PCRE软件的支持。

       Nginx服务器使用ngx_http_rewrite_module模块解析和处理Rewrite功能的相关配置。

       默认会自带ngx_http_rewrite_module模块,所以不需要单独编译安装。

2.  关于地址重写与地址转发的概念

     地址重写

       是为了实现地址标准化。

       当我们访问google.com与www.goolge.com都会响应www.google.com的页面。

       从客户端的角度来看,是两个地址,实际上,只是www.google.com在做响应。

       在访问google.com的过程,地址已经重写到了www.google.com上,然后www.google.com给客户端响应。

     地址转发

       将一个域名指到另一个域名的过程。

     区别:

        

3.  Nginx rewirte语法

          1.  if语法格式

          if  (condition)  {.........}

       if使用在server或location块中。

       conditon可以是下面这几种情况。

       1.  如果条件是变量名;值为空或者0时,if认为条件为false,其他值都为true。

         if   ($slow)  {

                             ......执行语句

                             }

                    2.  判断变量是否与字符串相等或者不等。

        if  ($request_method = POST) {

           return 403;

                            }

        =  或者 !=

        注意:字符串不需要使用引号。

 location / {
            root   html;
            index  index.html index.htm;
            if ($remote_addr = 192.168.0.105){
            return 403;
            }
        }
当客户端的IP地址为192.168.0.105访问网站的时候,会有403报错。

         3.  条件使用正则表达式进行匹配

            “~” 用正则来匹配(此处的正则区分大小写)

“~*”用正则来匹配(不区分大小写的正则)

"!~"与"~"相反

"!~*"与"!~*"相反

例子: 

location / {
            root   html;
            index  index.html index.htm;
            if ($http_user_agent ~ Chrome){
            return 403;
            }
        }
当客户端浏览器为谷歌浏览器的时候,网站响应403错误。
location / {
            root   html;
            index  index.html index.htm;
            if ($http_user_agent ~ Chrome){
            rewrite ^.*$ /ie.html;
            }
        }
访问站点的时候,出现错误:
500 Internal Server Error

为什么呢?

因为我设置重定向到ie.html,当请求访问重定向的地址的时候,又是一个Chrome发起的请求,这是一个循环重定向。如何解决这个问题呢?

location / {
  root html;
  index index.html index.htm;
  if ($http_user_agent ~ Chrome){
  rewrite ^.*$ /ie.html;    默认使用的是
  break;            必须使用break,不然会循环重定向
  }
}

  
在正则表达式中,可以使用小括号对变量值进行截取,在花括号中使用$1...$9引用截取的值
if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; }

     4.   条件中判断文件是否存在

           -f:如果请求的文件存在,条件为true,如果请求的文件不存在,条件为false。

           !-f:如果文件存在,条件为false;如果文件和目录都不存在,条件为false;如果文件不存在,但文件所在目录存在,条件为true。

       5.      条件中判断目录是否存在

              -d:如果请求的目录存在,条件为true,如果请求的目录不存在,条件为false。

           !-d:如果目录存在,条件为false;如果目录和父目录都不存在,条件为false;如果目录不存在,但父目录存在,条件为true。

       6.    条件中判断请求的目录或文件是否存在

           -e:如果请求的目录或文件存在,条件为true,如果请求的目录或文件不存在,条件为false。

             !-e:如果请求的文件和该文件所在路径上的目录都不存在,为true;否则为false。

       7.     条件中判断请求的文件是否可执行

           -x:如果请求的文件可执行,条件为true,否则为false。

           !-x:如果请求的不可执行,条件为true,否则为false。

   2.  break语法

        用于中断相同作用域中的其他nginx配置。

        break可以使用在server,location,if块中。

location / {
  if ($slow) {
  set $id $1    处于break之前,配置有效
  break;
  limit_rate 10k; 处于break之后,配置无效
  }
  ......       其他nginx配置,处于break上一层作用域,配置有效
}

 

   3.  return语法

        return  code  返回给客户端HTTP状态码,0~999

        return  URL   返回给客户端URL

        return  [text]  返回给客户端的响应体内容

   4.  rewrite语法

        rewrite  regex  replacement  [flag];

        regex  用于匹配URI的正则表达式。使用括号"()"标记要截取的内容 

          注意:rewrite指令接收到的URI为"/source",不包含"myweb.com"和"?agr=value1&agr2=value2"

        replacement  匹配成功后用于替换URI中被截取内容的字符串。

                replacement变量中支持Nginx全局变量的使用,常用的还有$uri和$args等。

        flag  用来设置rewrite对URI的处理行为

            last  大部分都使用这个flag

location / {
rewrite  ^(/myweb/.*)/media/(.*)\..*$    $1/mp3/$2.mp3  last;
rewrite  ^(/myweb/.*)/audio/(.*)\..*$    $1/mp3/$2.ra last;
}
如果某URI在第二行匹配成功并处理,nginx服务器不会继续使用第3行的配置匹配和处理新的URI.
但是其他的location块会重新匹配和处理新的URI           

            break  匹配成功后,将中断匹配

location / {
rewrite  ^(/myweb/.*)/media/(.*)\..*$    $1/mp3/$2.mp3  break;
rewrite  ^(/myweb/.*)/audio/(.*)\..*$    $1/mp3/$2.ra break;
}
如果某URI在第二行匹配成功并处理,nginx服务器将新的URI继续在该location块中使用第3行进行匹配和处理,不会将新的URI转向到其他location块,新的URI始终是在同一个location块中。 

            redirect  临时重定向URI,主要用在replacement变量不是以http://或者https://开头的情况下

            permanent  永久重定向URI

  5.  rewrite_log指令

      rewrite_log on | off;  是否开启URL重写日志的输出功能,默认为off,开启以后,以notice级别输出到error_log的日志文件中

  6.  set指令

      set variable value;  设置一个新的变量

      variable  使用$作为变量的第一个字符,不能与Nginx服务器的全局变量同名

      value  可以是字符串,其他变量或变量的组合

4.  Rewrite的使用

    1.  域名跳转

        1.  单个域名

server
{
        listen 80;
        server_name nacos.dev.zp.com;
        access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
        rewrite ^/ http://www.baidu.com/;


        location / {
#                add_header      Access-Control-Allow-Origin *;
                proxy_pass      http://nacos;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
         }

                location /devDist {
                    add_header Access-Control-Allow-Origin *;
                    root /website/demo.dev.zp.com;
                    index index.html;
         }
}        

        2.  多个域名

server
{
        listen 80;
        server_name nacos.dev.zp.com nacos.dev.zp.net;
        access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
        if ($host ~ zp\.com)
        {
        rewrite ^(.*) http://www.baidu.com$1 permanent;
        }
     if ($host !='nacos.dev.zp.com') {
rewrite ^/(.*)$ http://www.baidu.com/$1 permanent;
}
location / { # add_header Access-Control-Allow-Origin *; proxy_pass http://nacos; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /devDist { add_header Access-Control-Allow-Origin *; root /website/demo.dev.zp.com; index index.html; } } 

        3.  三级域名

server
{
        listen 80;
        server_name nacos.dev.zp.com nacos1.dev.zp.com;
        access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
        if ($host ~ ^(.*)\.dev\.zp\.com)
        {
        rewrite ^(.*) http://www.baidu.com;
        }

        location / {
#                add_header      Access-Control-Allow-Origin *;
                proxy_pass      http://nacos;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
         }

                location /devDist {
                    add_header Access-Control-Allow-Origin *;
                    root /website/demo.dev.zp.com;
                    index index.html;
         }
}                 

        4.  域名跳转到本地端口           

upstream tomcat {
   server 127.0.0.1:8080;
}
server {
    listen  80;
    server_name test.ceshi.com;
    root  /var/www/vhosts/ test.ceshi.com/;
  
    location / {
            proxy_pass http://tomcat ;
        }
}  

    2.  域名镜像

        1.  为整个网站做镜像

{
        listen 80;
        server_name nacos1.dev.zp.com;
        access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
        rewrite ^(.*) http://www.baidu.com$1 last;

}

{
        listen 80;
        server_name nacos2.dev.zp.com;
        access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
        rewrite ^(.*) http://www.baidu.com$1 last;

}

        2.  为某个子目录做镜像

                location ^~ /a {
                    add_header Access-Control-Allow-Origin *;
                    rewrite ^/a(.*) http://www.baidu.com$1 last;
         }
                location ^~ /b {
                    add_header Access-Control-Allow-Origin *;
                    rewrite ^/b(.*) http://www.baidu.com$1 last;
         }                

    3.  当访问http://abc.wangshibo.com跳转到http://www.wangshibo.com/wangshibo/abc/

方法一:这种方法浏览器地址会变www.wangshibo.com/wangshibo/abc
server {
        listen 80;
        server_name www.wangshibo.com;
        location / {
                root /data/wangshibo;
                index index.html;
        }
}
  
server {
        listen 80;
        server_name *.wangshibo.com;
        if ( $http_host ~* "^(.*)\.wangshibo\.com$") {
                set $domain $1;
                rewrite ^(.*) http://www.wangshibo.com/wangshibo/$domain/ break;
        }
}
 
方法二:当访问http://abc.wangshibo.com/*跳转到http://www.wangshibo.com/wangshibo/abc/*
server {
        listen 80;
        server_name *.wangshibo.com;
        root /usr/local/www;
        #这是里可以加多个目录,如果不加目录,会无法访问到abc.wangshibo.com/目录下的文件,如图片目录/images
        location ~ ^/(wangshibo|images|styles)/
        {
                proxy_redirect        off;
                proxy_set_header    Host   www.wangshibo.com;
                proxy_pass      http://192.168.1.2:8080;
        }
        location / {
                set $domain default;
                if ( $http_host ~* "^(.*)\.wangshibo\.com$") {
                        set $domain $1;
                }
                rewrite ^/(.*)    /wangshibo/$domain/$1 last;
        }
        access_log off;
}

    4.  访问一个域名http://yangjianbo.com自动跳转http://www.yangjianbo.com

1) 首先要保证不加www和加www的域名都要解析出来。
在DNS里添加yangjianbo.com和www.yangjianbo.com的解析,比如解析到111.110.11.18
@                             IN      A       111.110.11.18
www                         IN      A       111.110.11.18
 
解释:
A记录解析yangjianbo.com到111.110.11.18地址上,前面加@或者留空(留空默认就是@)
A记录解析www.yangjianbo.com到111.110.11.18地址上,前面加www
 
2)nginx配置不加www自动跳转到www的域名访问(80或443都一样),有下面两种方法实现:
 
方法一:
在conf/vhost/yangjianbo.conf文件中配置:
 
server {
        listen       80;
        server_name  www.yangjianbo.com yangjianbo.com;
 
        index index.jsp index.html index.php index.htm;
        root   /var/www/html;
  
       access_log  /data/nginx/logs/www.yangjianbo.com-access.log main;
       error_log  /data/nginx/logs/www.yangjianbo.com-error.log;
  
 
        if ($host = "yangjianbo.com") {
             rewrite ^/(.*)$ http://www.yangjianbo.com permanent;
        }
 
}
 
 
方法二(官方推荐这一种nginx的301跳转方法)
在conf/vhost/yangjianbo.conf文件中配置:
 
server {
          listen       80;
          server_name  yangjianbo.com;
          return       301 http://www.yangjianbo.com$request_uri;
}
           
server {
         listen      80;
         server_name www.yangjianbo.com;
 
        index index.jsp index.html index.php index.htm;
        root   /var/www/html;
  
       access_log  /data/nginx/logs/www.yangjianbo.com-access.log main;
       error_log  /data/nginx/logs/www.yangjianbo.com-error.log;
}

    5.  目录合并  

比如将/wang-123-456-789.html指向wang/123/456/wangshow_789.html
[root@test-huanqiu ~]# cat /usr/local/nginx/conf/vhosts/test.conf
server {
     listen 80;
     server_name www.wangshibo.com;
     rewrite ^/wang-([0-9]+)-([0-9]+)-([0-9]+)\.html$ http://www.wangshibo.com/wang/$1/$2/wangshow_$3.html last;
     root /var/www/html;
     index index.html index.php index.htm;
     access_log /usr/local/nginx/logs/image.log;

}
这样访问http://www.wangshibo.com/wang-123-456-789.html就会跳转到http://www.wangshibo.com/wang/123/456/wangshow_789.html

    6.  访问的目标文件和目录不存在的时候重定向跳转

server {
    listen 80;
    server_name www.wangshibo.com;
    if (!-e $request_filename) {
        rewrite ^/ http://www.wangshibo.com/sorry.html ;
    }
    root /var/www/html;
    index index.html index.php index.htm;
    access_log /usr/local/nginx/logs/image.log;
}

    7.  将站点根目录下某个目录指向二级目录

server {
    listen 80;
    server_name www.wangshibo.com;
    rewrite ^/([0-9a-z]+)pc/(.*)$ http://www.wangshibo.com/ops/$1/$2 last;
    root /var/www/html;
    index index.html index.php index.htm;
    access_log /usr/local/nginx/logs/image.log;
}
这样,访问http://www.wangshibo.com/huanqiupc的时候就会跳转到http://www.wangshibo.com/ops/huanqiu/
注意:上面的配置中的last修改为permanent或redirect都可以

    8.  访问http://www.wangshibo.com/g/4HG45SkZ 实际访问地址跳转为 http://110.10.88.99:8081/qun/share/view?code=4HG45SkZ

upstream  g_server {
        keepalive 64;
        server 110.10.88.99:8081 max_fails=2 fail_timeout=5 weight=100;
        }
 
    server {
        listen       80;
        server_name  www.wangshibo.com;
 
        rewrite ^/bcloud.(swf|html|js)(.*)$ http://hehe.wangshibo.com/bcloud.$1$2 last;
 
        root  /home/web/www;
        location ~ \.apk$ {
        max_ranges 0;
          }
 
        location ^~ /g {
            proxy_redirect off;
            proxy_set_header Host $host;
#           proxy_set_header Host $host:$remote_port;
#           proxy_set_header REMOTE_PORT $remote_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            client_max_body_size 1G;
            client_body_buffer_size 256k;
            proxy_connect_timeout 30;
            proxy_send_timeout 30;
            proxy_read_timeout 600;
            proxy_buffer_size 16k;
            proxy_buffers 4 32k;
            proxy_temp_file_write_size 64k;
            proxy_pass  http://g_server;
            #rewrite "/g/(.*$)"   www.wangshibo.com/qun/share/view?code=$1  break;
            rewrite "/g/(.*$)"   /qun/share/view?code=$1  break;
        }
    }

    9.  访问http://www.wangshibo.com/thumb/transcode 实际访问地址为 http://120.170.190.99:28080/transcode/thumb/transcode

upstream  thumb {
        keepalive 64;
        server 120.170.190.99:28080 max_fails=2 fail_timeout=5 weight=100;
    }
 
server {
        listen       80;
        server_name  www.wangshibo.com ;
 
        root   /home/web/www;
 
  location ^~ /thumb {
            proxy_pass  http://thumb;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
            client_max_body_size 1G;
            client_body_buffer_size 256k;
            proxy_connect_timeout 30;
            proxy_send_timeout 30;
            proxy_read_timeout 60;
            proxy_buffer_size 16k;
            proxy_buffers 4 32k;
            proxy_temp_file_write_size 64k;
            rewrite  "^/(.*)$"  /transcode/$1 break;
        }
}

    10.  访问http://www.wangshibo.com/wangshibo/ops就会跳转到http://www.wangshibo.com/ops/wangshibo

server {
   listen 80;
   server_name www.wangshibo.com;
   rewrite ^/wangshibo/(.*)$  http://www.wangshibo.com/$1/wangshibo last;
   root /var/www/html;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

    11.  访问http://www.wangshibo.com/ops/web 跳转到 http://www.wangshibo.com/web/ops/web/

server {
   listen 80;
   server_name www.wangshibo.com;
   rewrite ^/ops/(.*)$  http://www.wangshibo.com/$1/ops/$1 break;
   root /var/www/html;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

    12.  访问http://www.wangshibo.com/wang/123 实际访问地址跳转为 http://www.hehe.com/qun/share/view?code=123

server {
   listen 80;
   server_name www.wangshibo.com;
   rewrite ^/wang/(.*)$  http://www.hehe.com/qun/share/view?code=$1 last;
   root /var/www/html;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

  

  

    

        

    

    

  

      

            

                      

                       

posted @ 2018-02-12 17:43  奋斗史  阅读(423)  评论(0)    收藏  举报