那些年的记忆

习惯改变行为,行为决定命运。

Nginx的Rewrite规则

  • Nginx Rewrite规则的相关指令有if、rewrite、set、return、break等。

    break指令:作用是完成当前的规则集,不再处理rewrite指令。

    if指令:用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。if指令不支持嵌套,不支持多个条件&&和||处理。

    以下信息可以被指定为条件:

    1) 变量名,错误的值包括:空字符串"",或者任何以0开始的字符串;

    2) 变量比较可以使用"="和"!="运算符;

    3) 正则表达式模式匹配可以使用"~*"和"~"符号;

    4) "~"符号表示区分大小写民字母的匹配;

    5) "~*"符号表示不区分大小写字母的匹配;

    6) "!~"和"!~*"符号的作用刚好和"~"、"!~*"相反,表示不匹配;

    7) "-f"和"!-f"用来判断文件是否存在;

    8) "-d"和"!-d"用来判断目录是否存在;

    9) "-e"和"!-e"用来判断文件或目录是否存在;

    10) "-x"和"!-x"用来判断文件是否可执行;

    部分正则表达式可以在圆括号"()"内,其值可以通过后面的变量$1至$9访问;

    return指令:用于结束规则的执行并返回状态码给客户端。状态码可以使用这些值:204,400,402~406,408,410,411,413,416及500~504.些外,非标准状态码444将以不发送任何Header头的方式结束连接。

    rewrite指令:根据表达式来重定向URL,或修改字符串。

    如果替换串以http://开头,将会采用301或302跳转进行URL重定向

    rewrite     指令的最后一项参数为flag标记,支持的flag标记有:

    last         相当于Apache里的[L]标记,表示完成rewrite;

    break本条规则匹配完成后,终止匹配,不再匹配后面的规则;

    redirect返回302临时重定向,浏览器地址栏会显示跳转后的URL地址;

    premanent返回301永久重定向,浏览器地址栏会显示跳转后的URL地址;

    set指令:用于定义一个变量,并给变量赋值。变量的值可以为文本、变量及文本变量的联合;

    uninitialized_variable_warn指令:用于开启或关闭记录关于未初始化变量的警告信息,默认值为开启;

  • Nginx Rewrite可以用到的全局变量

    在if、location、rewrite指令中,可以使用以下全局变量:


  • $arg_PARAMETER#这个变量包含GET请求中,如果有变量PARAMETER时的值。

                $args                    #这个变量等于请求行中(GET请求)的参数,例如foo=123&bar=blahblah;

                $binary_remote_addr        #二进制的客户地址。

                $body_bytes_sent              #响应时送出的body字节数数量。即使连接中断,这个数据也是精确的。

                $content_length                #请求头中的Content-length字段。

                $content_type                   #请求头中的Content-Type字段。

                $cookie_COOKIE                #cookie COOKIE变量的值

                $document_root            #当前请求在root指令中指定的值。

                $document_uri                #与$uri相同。

                $host                #请求主机头字段,否则为服务器名称。

                $hostname                #设置机器的主机名作为返回主机名

                $http_HEADER

                $is_args                如果有$args参数,这个变量等于”?”,否则等于”",空值。

                $http_user_agent            #客户端agent信息

                $http_cookie            #客户端cookie信息

                $limit_rate            #这个变量可以限制连接速率。

                $query_string            #与$args相同。

                $request_body_file            #客户端请求主体信息的临时文件名。

                $request_method            #客户端请求的动作,通常为GET或POST。

                $remote_addr                #客户端的IP地址。

                $remote_port            #客户端的端口。

                $remote_user            #已经经过Auth Basic Module验证的用户名。

                $request_completion            #如果请求结束,设置为OK. 当请求未结束或如果该请求不是请求链串的最后一个时,为空(Empty)。

                $request_method            #GET或POST

                $request_filename                #当前请求的文件路径,由root或alias指令与URI请求生成。

                $request_uri            #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。不能修改。

                $scheme         #HTTP方法(如http,https)。

                $server_protocol            #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。

                $server_addr            #服务器地址,在完成一次系统调用后可以确定这个值。

                $server_name            #服务器名称。

                $server_port            #请求到达服务器的端口号。

                $uri                         #不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。该值有可能和$request_uri 不一致。 $request_uri是浏览器发过来的值。该值是rewrite后的值。例如做了internal redirects后。

  • if的多重判断实例

    testversionurl.conf

##
#new url by Jarvan 2013.10.15
##
set $version "";
set $version_id "";
set $state_type "";
set $click_type "";
set $table_name "";
set $page_num "";
set $diplay_num "";
if ( $request_uri ~* "/leaf/(.*)\?(.*)$" ){
    rewrite ^/leaf/(.*)$/leaf/index.html last;
}
if ( $request_uri ~* "/([0-9]+)/(category|feedback|install|launcher|register|thirdpartylogin)/([A-Za-z]+)\?(.*)$" ){
    set $version_id $1;
}
if ( $request_uri ~* "/([0-9]+)/state/([A-Za-z]+)\?(.*)$" ){
    set $version_id $1;
    set $state_type $2;
}
if ( $request_uri ~* "/([0-9]+)/click/([A-Za-z]+)\?p=(.*)$" ){
    set $version_id $1;
    set $click_type $2;
}
if ( $request_uri ~* "/([0-9]+)/journal/([0-9]+)\?p=([0-9]+)&did=([0-9]+)(.*)$"){
    set $version_id $1;
    set $table_name $2;
    set $page_num $3;
    set $diplay_num $4;
}
if ( $version_id ~ "(214425562|760866600|1679171379|3801106308)" ){
    set $version "1.00";
}
if ( $version_id ~ "(673810490|2551210251|3023280032|4261659903)" ){
    set $version "1.10";
}
if ( $version != "" ){
    rewrite ^/([0-9]+)/(category|feedback|install|launcher|register|state|thirdpartylogin)/([A-Za-z]+)$/$version/$version_id/$2/$3.php last;
    rewrite ^/([0-9]+)/state/([A-Za-z]+)$/$version/$version_id/state/$state_type.html last;
    rewrite ^/([0-9]+)/click/([A-Za-z]+)$/$version/$version_id/click/$click_type.php last;
    rewrite ^/([0-9]+)/journal/([0-9]+)$/$version/$version_id/journal/journal.php?did=$diplay_num&id=$table_name&s=$page_num? last;
}

4. 网站配置实例

server {
    listen   80 ;  #listen for ipv4; this line is default and implied
    #log_format testversion '$remote_addr\t$time_local'
    #'\t"$request"\t$status\t$body_bytes_sent'
    #'"\t$http_referer"\t"$http_user_agent"';
    access_log /var/log/nginx/testversion.access.log testversion;
    #rewrite by Jarvan 2013.10.15
    rewrite_log on;
    error_log /var/log/nginx/testversion.error.log notice;
    root /home/testversionurl;
    index index.php  index.html index.htm;
            
    server_name app.xxxx.net;
    location / {
        index index.html index.php;
        #if (!-e $request_filename)
        #{
        #      rewrite ^/(.+)$ /index.php last;
        #}
    }
            
    location /doc/ {
        alias /usr/share/doc/;
        autoindex on;
        allow 127.0.0.1;
        allow ::1;
        deny all;
    }
    location /html/ {
        if ( !-f $request_filename ){
            rewrite ^/html/([0-9]+).html$ /swift/1.20/4261659903/click/info.php last;
        }
    }
    #location /favicon.ico {
    #log_not_found off;
    #access_log off;
    #}
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        # With php5-fpm:
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /home/testversionurl$fastcgi_script_name;
        include fastcgi_params;
    }
    ##
    # old rewrite
    ##
    #if ( $request_uri ~* "/userpic\?i=(.*)&x=(.*)&y=(.*)&z=(.*)$")
    if ( $request_uri ~* "/userpic\?i=(.*)&x=(.*)&y=(.*)&z=(.*)$")
        {
            set $dirc $1;
            rewrite ^/(.+)$ /userImg/$dirc.png last;
        }
    ##
    #new url by Jarvan 2013.10.15
    ##
    set $version "";
    set $version_id "";
    set $state_type "";
    set $click_type "";
    set $table_name "";
    set $page_num "";
    set $diplay_num "";
    if ( $request_uri ~* "/leaf/(.*)\?(.*)$" ){
        rewrite ^/leaf/(.*)$/leaf/index.html last;
    }
    if ( $request_uri ~* "/([0-9]+)/(category|feedback|install|launcher|register|thirdpartylogin|tagcloud|expert)/([A-Za-z]+)\?(.*)$" ){
        set $version_id $1;
    }
    if ( $request_uri ~* "/([0-9]+)/state/([A-Za-z]+)\?(.*)$" ){
        set $version_id $1;
        set $state_type $2;
    }
    if ( $request_uri ~* "^/([0-9]+)/click/([A-Za-z]+)\?p=([0-9]+)&(.*)$" ){
        set $version_id $1;
        set $click_type $2;
        set $page_num $3;
    }
    if ( $request_uri ~* "/([0-9]+)/journal/([A-Za-z0-9]+)\?p=([0-9]+)&did=([0-9]+)(.*)$"){
        set $version_id $1;
        set $table_name $2;
        set $page_num $3;
        set $diplay_num $4;
    }
    if ( $version_id ~ "(214425562|760866600|1679171379|3801106308)" ){
        set $version "1.00";
    }
    if ( $version_id ~ "(2551210251|3023280032)" ){
        set $version "1.10";
    }
    if ( $version_id ~ "(4261659903|673810490)" ){
        set $version "1.20";
    }
    if ( $version != "" ){
        rewrite ^/([0-9]+)/(feedback|install|launcher|register|state|thirdpartylogin|tagcloud|expert)/([A-Za-z]+)$/swift/$version/$version_id/$2/$3.php break;
        rewrite ^/([0-9]+)/category/full$       /swift/$version/$version_id/category/full.json break;
        rewrite ^/([0-9]+)/category/([A-Za-z]+)$        /swift/$version/$version_id/category/$2.php break;
        rewrite ^/([0-9]+)/state/([A-Za-z]+)$/swift/$version/$version_id/state/$state_type.html break;
        rewrite ^/([0-9]+)/click/info$/html/$page_num.html break;
        rewrite ^/([0-9]+)/click/([A-Za-z]+)$/swift/$version/$version_id/click/$click_type.php break;
        rewrite ^/([0-9]+)/journal/([0-9]+)$/swift/$version/$version_id/journal/journal.php?did=$diplay_num&id=$table_name&s=$page_num? break;
        rewrite ^/([0-9]+)/journal/([A-Za-z]+)$/swift/$version/$version_id/journal/suite.php?did=$diplay_num&id=$table_name&s=$page_num? break;
    }
}


Q&A:

1. 如何查看rewrite后的URL地址以及匹配的哪条规则?

答:在Nginx.conf(或者站点配置文件也行)中打开rewrite_log即可(可以写在http{},server{},location{},if{}),如:

#开启重写日志

rewrite_log on;

#把error_log的级别调整到 notice

error_log /var/log/nginx/testversion.error.log notice;

2. 如何处理rewrite重定向后的参数

答:默认的情况下,在进行rewrite后都会自动添加上旧地址中的参数部分,而这对于重定向到的新地址来说可能是多余。虽然不会对重定向的结果造成影响,但是新地址中包含有多余的“xxx=xxx”时,总会觉得不爽。

    如:

原地址:http://test.versionurl/4261659903/journal/5001.php?p=4

默认的写法是:rewrite ^/([0-9]+)/journal/([0-9]+).php$ /$version/$version_id/journal/journal.php?did=2125970617&id=$table_name&s=$page_num last;

重定向后的结果:http://test.versionurl/4261659903/journal/journal.php?did=2125970617&id=5001&s=2&p=2

改写成(关键点就在于"?"这个尾缀):rewrite ^/([0-9]+)/journal/([0-9]+).php$ /$version/$version_id/journal/journal.php?did=2125970617&id=$table_name&s=$page_num? last;

重定向后的结果:http://test.versionurl/4261659903/journal/journal.php?did=2125970617&id=5001&s=2

假如想保留某个特定的参数可以用Nginx本身自带的$arg_PARAMETER参数实现。

如:rewrite  ^/test.php   /new?p=$arg_p?  last或permanent;  

参见:http://www.yeeann.com/archives/165.html


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。