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;
}
                    
                
                
            
        
浙公网安备 33010602011771号