Nginx:rewrite 的幾個技巧

在軟件的發(fā)布中,我們經(jīng)常會使用到 Nginx,Nginx 的功能非常的龐雜,其中 rewrite 是一個非常常用的功能模塊,本文介紹 rewrite 的基本概念和幾個小技巧。
rewrite 是 Nginx 中的一個模塊,這個模塊用來重定向頁面,在 rewrite 模塊中包含了幾個指令來實現(xiàn)不同的功能:
return
rewrite
if
return 指令
return 指令是 rewrite 模塊中非常常用的一個指令,可以幫助我們做重定向和一些簡單的返回。
語法
return?code?text;
return?code?URL;
return?URL;
return 指令的語法由兩個或三個部分組成:
return:關(guān)鍵字
code:http 狀態(tài)碼,當(dāng)沒有設(shè)置 code 時,默認(rèn)使用 302
text 或 URL:返回的字符串或跳轉(zhuǎn)的地址
使用范圍
server 節(jié)點
location 節(jié)點
if 塊中

在 server 節(jié)點中的 return 的優(yōu)先級要高于 location 節(jié)點的 return,不管 return 指令寫在 location 節(jié)點的上方還是下方
在 return 指令中使用 code,經(jīng)常會用到 301 或 302 ,區(qū)別如下:
301:永久重定向,例如訪問 a.com,通過 return 使用 301 重定向到了 b.com,然后修改 return 的地址為 c.com,訪問 a.com,還是訪問的 b.com,因為被緩存了
302:臨時重定向,例如訪問 a.com,通過 return 使用 302 重定向到了 b.com,然后修改 return 的地址為 c.com,訪問 a.com,會跳轉(zhuǎn)到 c.com,不會被緩存
rewrite 指令
可以根據(jù)指定的正則表達式將用戶請求的 url 轉(zhuǎn)換成一個新的 url 進行重定向。
語法
rewrite?regex?replacement?[flag];
return 指令的語法四個部分組成:
rewrite:關(guān)鍵字
regex:正則表達式,用于匹配用戶請求的 url 地址
replacement:新的 url 地址,當(dāng)?shù)刂烽_頭為 http 或 https ,默認(rèn)為 302 重定向
flag:替換后的 url 根據(jù) flag 進行處理,flag 有四個值
last:使用 replacement 的地址重新進行 location 匹配
break:會停止后面腳本的執(zhí)行
redirect:返回 302 重定向,地址欄顯示重定向后的url
permanent:返回 301 重定向,地址欄顯示重定向后的url
使用范圍
server 節(jié)點
location 節(jié)點
if 塊中

rewrite 指令的適用范圍和 return 指令的是一致的,優(yōu)先級也相同
當(dāng) rewrite 指令和 return 指令同時存在時,如果 rewrite 最后的 flag 不是 break,會繼續(xù)執(zhí)行 rewrite 之后的 return 指令
沒有指定 flag 的情況下,默認(rèn)為 302 重定向
if 指令
通過 if 指令進行一些條件的判斷,然后進行 return、rewrite 或是其他的一些處理。
語法
if(condition){
}
使用范圍
server 節(jié)點
location 節(jié)點

if 判斷的一些規(guī)則
變量和字符串做比較,使用 = 或 !=
將變量和正則表達式做比較:
大小寫敏感:~ 或 !~
大小寫不敏感:~* 或 !~* ,例如上圖中的示例
檢查文件是否存在,使用 -f 或 !-f
檢查目錄是否存在,使用 -d 或 !-d
示例
下面以近期用到的兩個場景來演示實際的用法。
PC 端跳轉(zhuǎn)到移動端
場景描述:
PC 端發(fā)布后的地址為:192.168.0.1
移動端采用 H5 開發(fā),發(fā)布后的地址:192.168.0.1:81
在手機上訪問 PC 端地址,跳轉(zhuǎn)到移動端
PC 端和移動端使用同一個接口地址,接口地址是在 PC 端使用 /api 進行的代理
只有頁面的請求跳轉(zhuǎn)到移動端,接口的請求不需要跳轉(zhuǎn)
配置如下:
server?{
????listen???????80;
????server_name??localhost;
????set?$flag?0;
????if?($http_user_agent?~*?(mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)?)?{
??????set?$flag?"${flag}1";
????}
????if?($request_uri?!~*?/api/)?{
??????set?$flag?"${flag}2";
????}
????if?($flag?=?"012")?{
???????rewrite??^(.*)????http://192.168.0.1:81??permanent;
????}
????location?/?{
????????root???/usr/share/nginx/html;
????????index??index.html?index.htm;
????}
????location?/api/?{
??????proxy_pass?http://192.168.0.1:5000/;
????}
????error_page???500?502?503?504??/50x.html;
}
兩個條件都滿足的情況下,進行跳轉(zhuǎn)
設(shè)備類型為移動端
請求的路由中不包含 /api
因為 if 指令的條件的限制,不能再一個 condition 中使用多條件,所以定義了一個變量 $flag 來做判斷
將源地址中的特定參數(shù)傳遞到目標(biāo)地址
場景描述:
上面的示例中,跳轉(zhuǎn)到移動端后進入的是移動端的登錄頁面,因為沒有登錄人的身份
現(xiàn)在假設(shè) PC 端的地址后有 authcode 的參數(shù)用來確定身份,除此之外還有其他的參數(shù),例如:
http://192.168.0.1?id=xxxxx&authcode=xxxxxxxx需要再跳轉(zhuǎn)后將 authcode 傳遞到移動端的地址后面,例如:
http://192.168.0.1:81?authcode=xxxxxxxx移動端可以做解析實現(xiàn)直接登錄
配置如下:

