nginx rewrite (不支持if 嵌套也不支持邏輯或和邏輯並)

apache的rewrite是支持或者的,用個OR就可以,如果不加OR,多個RewriteCond 羅列累加就是並且的意思。然後nginx的rewrite就沒有這麼好了。那麼如何去實現這樣複雜的功能呢?這就用到了標記功能。

現在出一個簡單的需求: 要求訪問uri以 /abc/開頭的請求,並且user_agent帶有ie6或者firefox關鍵詞的請求需要禁止訪問。
實現方法爲:

          set $rule 0;
                if ($document_uri ~ '^/abc')
                {
                        set $rule "${rule}1";
                }
                if ($http_user_agent ~* 'ie6|firefox')
                {
                       set $rule "${rule}2";
                }
                if ($rule = "012")
                {
                        deny all;
                }

這樣就可以實現了。
然後在我實踐過程中,發現一個問題,就是如果定義超過3條rule,當條件中包含兩條和兩條以上的規則同時存在是,需要把兩條規則的條件寫到第4條規則前面。
例如,有一個這樣的需求:實現rewrite的總前提是,所有請求必須以^/abc 目錄爲開頭。其餘規則如下:
1. user_agent 包含 'ipone' 或者'ipad'  或者'ipod' 的請求需要把 *htm 轉發爲 *html;
2. user_agent 不包含 'ipone' 或者'ipad'  或者'ipod' 並且user_agent 包含'ucweb'的請求需要把*htm 轉發爲 *html;
3. user_agent 不包含 'ipone' 或者'ipad'  或者'ipod' 並且user_agent 不包含'ucweb'的請求需要把*html 轉發爲 *htm;

規則語句爲:
     set $rule 2;
        if ($document_uri ~* '^/abc')
        {
            set $rule "${rule}1";
        }
        if ($http_user_agent ~* 'ipad|iphone|ipod')
        {
            set $rule "${rule}2";
        }
        if ($rule = "212")
        {
            rewrite ^(.*)\.htm$ $1\.html redirect;
        }
        if ($http_user_agent !~* 'ipad|iphone|ipod')
        {
            set $rule "${rule}3";
        }
        if ($http_user_agent !~* 'ucweb')
        {
            set $rule "${rule}4";
        }
        if ($http_user_agent ~* 'ucweb')
        {
            set $rule "${rule}5";
        }
        if ($rule = "2134")
        {
            rewrite ^(.*)\.html$ $1\.htm redirect;
        }
        if ($rule = "2135")
        {
            rewrite ^(.*)\.htm$ $1\.html redirect;
        }

注意,上面規則把 $rule = "212" 放到了上面,如果放到下面則不能實現跳轉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章