透過 nginx 判斷 device
set $mobile_rewrite do_not_perform;
if ($http_user_agent ~* "(mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)") {
set $mobile_rewrite perform;
rewrite ^/$ pc/index.html last;
rewrite ^(.*)$ /mobile$1 break;
}
if ($mobile_rewrite = perform) {
# root /Users/chuchengyang/cases/nginx-test/mobile;
bla... bla...
}
rewrite
Nginx 的 ngx_http_rewrite_module 模組
「ngx_http_rewrite_module」是 Nginx 預設啟用的模組,可以用來將符合某個正規表示式的網址轉成別的網址。另外,它也提供了一些如if、break、return等常用的流程控制命令。
若要使用ngx_http_rewrite_module模組來實現轉址功能,我們可以在server區塊或是其子區塊內使用「ngx_http_rewrite_module」模組提供的rewrite命令。例如:
rewrite ^ /123;
以上命令,可以將所有的網址都轉址到/123,並且繼續執行同一個區塊後續的命令。也就是說,/123也還是可以之後再使用「ngx_http_rewrite_module」模組所提供的命令轉成其它位址。這邊要注意的是,rewrite命令無法去更動到原始網址中的查詢(Query)參數,也就是問號?和其後面的字串。
rewrite命令也可以加入第三個參數,來進行更細微的控制,第三個參數值可以是以下幾種之一:
- **
last:**使這個rewrite命令的正規表示式成立且轉址(內部)之後,不會再去執行同一個區塊後續的命令,而是會直接以新的位址來去尋找符合的location區塊再重新去處理它。 - **
break:**使這個rewrite命令的正規表示式成立且轉址(內部)之後,不會再去執行同一個區塊後續的命令。 - **
redirect:**使這個rewrite命令的正規表示式成立且轉址之後,直接以 HTTP 的 302 狀態(Moved Temporarily)來回應客戶端,使其暫時地使用新網址再發送一次請求。 - **
permanent:**使這個rewrite命令的正規表示式成立且轉址之後,直接以 HTTP 的 301 狀態(Move Permanently)來回應客戶端,使其使用新網址再發送一次請求,並讓客戶端知道原本的網址已經被永久轉移到新網址了。
如果rewrite命令的第三個參數不是redirect或是permanent,則轉移過去的位址最好只能是以斜線/開頭的路徑,也就是要在同一個server區塊下處理的資源。反之,如果要在不同的server區塊甚至是不同的伺服器主機間進行轉址的話,rewrite命令的第三個參數就使用redirect或是permanent吧!
藉由正規表示式的群組功能,我們可以將原先位址中的部份字串,動態填入至新的位址中。例如:
rewrite ^/api/(.*)$ /api/v1/$1;
以上命令,可以將/api/xxx或是/apt/xxx/yyy等位址,轉成/api/v1/xxx或是/apt/v1/xxx/yyy。
另外,在新的位址中,也可以使用$scheme變數來取得原先網址中所使用的通訊協定。例如:
rewrite ^/(.*)$ $scheme://new-domain.com/$1 redirect;
以上命令,可以將所有的網址轉到新的網域(new-domain.com),並且保留原先網址的通訊協定。當然,以這個例子來說,比較好的作法是,直接利用$request_uri變數來取得原先網址中不包括前段通訊協定和伺服器名稱的內容,如此一來就可以省下使用正規表示式來處理的運算資源。如下:
rewrite ^ $scheme://new-domain.com$request_uri? redirect;
別忘了在使用$request_uri變數時,最好在其後加上問號?,才能避免網址的查詢參數被重複添加。例如原本的網址是http://127.0.0.1/api?a=10,如果沒有在$request_uri變數之後加上問號?,轉出來就會是http://new-domain.com/api?a=10?a=10。
如果想進行更進階的控制,可以使用if、break和return命令。if命令可以判斷一個變數是否不是0、false或是空字串,如果不是的話,就會去執行該if區塊中的命令。break可以略過同一個區塊中後續要執行的命令。return命令會直接發送 HTTP 回應,完成路由。return命令的參數必須要有 HTTP 狀態碼或是要轉址到的新網址,如果兩者都有的話,HTTP 狀態碼為第一個參數,網址則為第二個參數。
例如以下命令,直接以 HTTP 的 403 狀態(Forbidden)來回應客戶端。
return 403;
例如以下命令,直接以 HTTP 的 302 狀態(Moved Temporarily)來回應客戶端,使其暫時地使用新網址再發送一次請求。
return 302 https://magiclen.org;
常用的轉址設定
底下以不同的情境,來區分 Nginx 的設定檔寫法。