nginx rewrite

當運維遇到要重寫狀況時,每每是要程序員把重寫規則寫好後,發給你,你再到生產環境下配置。對於重寫規則說到底就是正則匹配,作運維的豈能對正則表達式不瞭解的?最起碼最基本的正則表達式會寫。套用一句阿里的話(某網友說是阿里說的,不清楚究竟是不是出自阿里)「不懂程序的運維,不是好運維;不懂運維的開發,不是好開發。」。 正則表達式也是一門語言哈。當你學習一門語言時,必然會遇到該門語言的正則表達式這章節的。 在這裏推薦一本很是好的正則表達式書,包含經常使用的語言的正則寫法如sed、perl、bash、awk、php、c#、java、javascript、python、ruby等等,《Regular Expressions Cookbook, 2nd Edition》,也有中文版的,你們能夠到網絡上找找。javascript

 

 

本文介紹nginx的重寫模塊,建立重寫規則嚮導,便於快捷正確的建立新的重寫規則,不求救於人。同時,若是想把apache轉換成nginx,重寫規則也是要改的咯。php

 

一. rewrite模塊介紹

 

nginx的重寫模塊是一個簡單的正則表達式匹配與一個虛擬堆疊機結合。依賴於PCRE庫,所以須要安裝pcre。根據相關變量重定向和選擇不一樣的配置,從一個location跳轉到另外一個location,不過這樣的循環最多能夠執行10次,超事後nginx將返回500錯誤。同時,重寫模塊包含set指令,來建立新的變量並設其值,這在有些情景下很是有用的,如記錄條件標識、傳遞參數到其餘location、記錄作了什麼等等。html

 

二. rewrite模塊指令

 

breakjava

 

語法:breakpython

默認值:nonenginx

使用字段:server, location, if程序員

 

完成當前設置的重寫規則,中止執行其餘的重寫規則。web

 

if正則表達式

 

語法:if (condition) { … }apache

默認值:none

使用字段:server, location

 

注意:儘可能考慮使用try_files代替。判斷的條件能夠有如下值:

 

  1. 一個變量的名稱:空字符傳「」或者一些「0」開始的字符串爲false。

     

  2. 字符串比較:使用=或!=運算符

     

  3. 正則表達式匹配:使用~(區分大小寫)和~*(不區分大小寫),取反運算!~和!~*。

     

  4. 文件是否存在:使用-f和!-f操做符

     

  5. 目錄是否存在:使用-d和!-d操做符

     

  6. 文件、目錄、符號連接是否存在:使用-e和!-e操做符

     

  7. 文件是否可執行:使用-x和!-x操做符

 

return

 

語法:return code

默認值:none

使用字段:server, location, if

 

中止處理併爲客戶端返回狀態碼。非標準的444狀態碼將關閉鏈接,不發送任何響應頭。可使用的狀態碼有:204,400,402-406,408,410, 411, 413, 416與500-504。若是狀態碼附帶文字段落,該文本將被放置在響應主體。相反,若是狀態碼後面是一個URL,該URL將成爲location頭補值。沒有狀態碼的URL將被視爲一個302狀態碼。

 

rewrite

 

語法:rewrite regex replacement flag

默認值:none

使用字段:server, location, if

 

按照相關的正則表達式與字符串修改URI,指令按照在配置文件中出現的順序執行。能夠在重寫指令後面添加標記。

 

注意:若是替換的字符串以http://開頭,請求將被重定向,而且再也不執行多餘的rewrite指令。

 

尾部的標記(flag)能夠是如下的值:

 

  • last – 中止處理重寫模塊指令,以後搜索location與更改後的URI匹配。

     

  • break – 完成重寫指令。

     

  • redirect – 返回302臨時重定向,若是替換字段用http://開頭則被使用。

     

  • permanent – 返回301永久重定向。

 

rewrite_log

 

語法:rewrite_log on | off

默認值:rewrite_log off

使用字段:server, location, if

變量:無

 

啓用時將在error log中記錄notice級別的重寫日誌。

 

set

 

語法:set variable value

默認值:none

使用字段:server, location, if

 

爲給定的變量設置一個特定值。

 

uninitialized_variable_warn


語法:uninitialized_variable_warn on|off

默認值:uninitialized_variable_warn on

使用字段:http, server, location, if

 

控制是否記錄未初始化變量的警告信息。

 

三. 重寫規則組成部分

 

3.1 任何重寫規則的第一部分都是一個正則表達式

 

可使用括號來捕獲,後續能夠根據位置來將其引用,位置變量值取決於捕獲正則表達式中的順序,$1引用第一個括號中的值,$2引用第二個括號中的值,以此類推。如:

 

^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$

 

$1是兩個小寫字母組成的字符串,$2是由小寫字母和0到9的數字組成的5個字符的字符串,$3將是個文件名,$4是png、jpg、gif中的其中一個。

 

3.2 重寫規則的第二部分是URI

 

請求被改寫。該URI可能包含正則表達式中的捕獲的位置參數或這個級別下的nginx任何配置變量。如:

 

/data?file=$3.$4

 

若是這個URI不匹配nginx配置的任何location,那麼將給客戶端返回301(永久重定向)或302(臨時重定向)的狀態碼來表示重定向類型。該狀態碼能夠經過第三個參數來明確指定。

 

3.3 重寫規則的第三部分

 

第三部分也就是尾部的標記(flag)。 last標記將致使重寫後的URI搜索匹配nginx的其餘location,最多可循環10次。如:

 

rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4 last;

 

break指令能夠當作自身指令。如:

 

if ($bwhog) {

    limit_rate 300k;

    break;

}

 

另外一箇中止重寫模塊處理指令是return, 來控制主HTTP模塊處理請求。 這意味着,nginx直接返回信息給客戶端,與error_page結合爲客戶端呈現格式化的HTML頁面或激活不一樣的模塊來完成請求。若是狀態碼附帶文字段落,該文本將被放置在響應主體。相反,若是狀態碼後面是一個URL,該URL將成爲location頭補值。沒有狀態碼的URL將被視爲一個302狀態碼。如:

 

location = /image404.html {

    return 404 "image not found\n";

}

 

四. 實例

 

http {

    # 定義image日誌格式

    log_format imagelog '[$time_local] ' $image_file ' ' $image_type ' ' $body_bytes_sent ' ' $status;

    # 開啓重寫日誌

    rewrite_log on;

 

    server {

        root /home/www;

 

        location / {

            # 重寫規則信息

            error_log logs/rewrite.log notice;

            # 注意這裏要用‘’單引號引發來,避免{}

            rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4;

            # 注意不能在上面這條規則後面加上「last」參數,不然下面的set指令不會執行

            set $image_file $3;

            set $image_type $4;

        }

 

        location /data {

            # 指定針對圖片的日誌格式,來分析圖片類型和大小

            access_log logs/images.log main;

            root /data/images;

            # 應用前面定義的變量。判斷首先文件在不在,不在再判斷目錄在不在,若是還不在就跳轉到最後一個url裏

            try_files /$arg_file /image404.html;

        }

        location = /image404.html {

            # 圖片不存在返回特定的信息

            return 404 "image not found\n";

        }

}

 

五. 建立新的從新規則

 

在接到要建立新的重寫規則時,要弄清楚需求是什麼樣的,再決定怎麼作。畢竟重寫也是耗資源的有效率之分的。 下面的這些問題有些幫助的:

 

  1. 你的URL的模式是什麼樣的?

     

  2. 是否有一個以上的方法來實現?

     

  3. 是否須要捕獲URL部分做爲變量?

     

  4. 重定向到另外一個web上能夠看到個人規則?

     

  5. 是否要替換查詢的字符串參數?

 

檢查網站或應用程序佈局,清楚URL模式。囉嗦一句:我一而再再而三的強調,運維不能與開發脫節,運維要參與到開發當中。若是有不止一種方法實現,建立一個永久重定向。同時,定義一個重寫規範,來使網址清潔,還能夠幫助網站更容易被找到。

 

實例1. 要將home目錄重定向到主頁面上,目錄結構以下:

 

/

/home

/home/

/home/index

/home/index/

/index

/index.php

/index.php/

 

重寫規則以下:

 

rewrite ^/(home(/index)?|index(\.php)?)/?$ $scheme:

//$host/ permanent;

 

指定$scheme和$host變量,由於要作一個永久重定向並但願nginx使用相同的參數來構造URL。

 

實例2. 若是想分別記錄各個部分的URL,可使用正則表達式來捕獲URI,而後,給變量分配指定位置變量,見上面的實例。

 

實例3. 當重寫規則致使內部重定向或指示客戶端調用該規則自己被定義的location時,必須採起特殊的動做來避免重寫循環。如:在server配置段定義了一條規則帶上last標誌,在引用location時,必須使用break標誌。

 

server {

    rewrite ^(/images)/(.*)\.(png|jpg|gif)$ $1/$3/$2.$3 last;

    location /images/ {

        rewrite ^(/images)/(.*)\.(png|jpg|gif)$ $1/$3/$2.$3 break;

    }

}

 

實例4. 做爲重寫規則的一部分,傳遞新的查詢字符串參數是使用重寫規則的目標之一。 如:

 

rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;

 

nginx重寫規則提及來挺簡單的,作起來就難,重點在於正則表達式,同時,還須要考慮到nginx執行順序。

相關文章
相關標籤/搜索