天天看點

Nginx rewrite配置規則

作為一個被廣泛用于反向代理的高性能WEB伺服器,Nginx通常處于承接網站流量的最前端。在實際項目中,經常會用Nginx對特定的用戶端請求做改寫(即rewrite)後傳回或将改寫後的request_url傳給後端real server做業務邏輯的處理。

本文是對nginx rewrite規則的學習筆記,參考資料主要來自官方文檔。

1. Nginx rewrite配置文法說明

Syntax:  rewrite regex replacement [flag];
Default: —
Context: server, location, if
           

上面是Nginx文檔對rewrite文法規則的說明,可知rewrite配置由4部分構成:

1)關鍵字rewrite表明這是一個rewrite規則

2)正規表達式regex用于篩選滿足regex條件的client request uri

3)replacement用于替換uri中命中regex模式的部分

4)可選參數flag用于控制Nginx對滿足本條rewrite規則的uri的後續處理行為

還可看到,rewrite配置可以位于server或location區塊(一個典型的Nginx配置檔案通常由http ==> server ==> location三個層級構成),還可以與if條件文法結合使用。

備注:Nginx的if配置項在使用不當時會引發詭異行為(可參考nginx wiki的If Is Evil這篇文章),通常不推薦新手使用。

2. rewrite規則的具體行為

rewrite的文法規則比較簡單,但實際配置中,細節才會決定最終的rewrite行為是否符合我們的預期。

下面是對Nginx rewrite行為的詳細說明,隻有真正意識到可能存在的坑并搞懂這些規則細節,才能真正駕馭rewrite配置。

1)若request uri與rewrite指定的regex比對成功,則比對的部分會被nginx用replacement替換

2)若同一個配置區塊存在多條rewrite規則,則nginx會按這些rewrite規則在配置檔案的出現順序對request uri進行比對

3)借助flag參數可控制nginx對命中目前rewrite規則且改寫後的新uri的後續處理行為,具體規則如下:

a. flag = last表示uri rewrite完成後就跳出本區塊,然後根據rewrite後的新uri重新搜尋符合條件的location區塊。可見,nginx對client request的處理流程會繼續向後走。是以,可能存在這種情況:新uri又比對到了同一個區塊,進而導緻死循環(事實上,nginx最多會循環10次)!這個坑在實際配置中一定要注意。

b. flag = break表示uri rewrite完成後就跳出本區塊,并且nginx會直接将rewrite後的新uri傳回,也即,nginx對uri的處理已完成,不會再繼續用改寫後的uri比對其他location區塊。

c. flag = redirect表示nginx會傳回一個http狀态碼為302的臨時重定向url,适用于本條rewrite配置的replacement部分不以http或https開頭的場合。

d. flag = permanent表示nginx會傳回一個http狀态碼為301的永久重定向url。

4)若replacement部分包含新的請求參數,則原uri的請求參數會追加在replacement包含的請求參數之後;若不希望原uri參數被追加,則可以”?”作為replacement的結尾來阻止追加行為,示例如下:

rewrite ^/users/(.*)$ /show?user=$1? break;
           

5)若regex部分包含“}”或“;”,則整個表達式都必須用單引号或雙引号括起來

以上規則中,flag參數的行為需要重點關注,尤其是last和break的差別。

3. 參考資料

  1. Nginx Doc: rewrite
  2. Nginx Doc: if directive
  3. Nginx Wiki: If Is Evil

繼續閱讀