Nginx:rewrite 的幾個技巧

在軟件的發佈中,我們經常會使用到 Nginx,Nginx 的功能非常的龐雜,其中 rewrite 是一個非常常用的功能模塊,本文介紹 rewrite 的基本概念和幾個小技巧。

rewrite 是 Nginx 中的一個模塊,這個模塊用來重定向頁面,在 rewrite 模塊中包含了幾個指令來實現不同的功能:

  • return
  • rewrite
  • if

return 指令

return 指令是 rewrite 模塊中非常常用的一個指令,可以幫助我們做重定向和一些簡單的返回。

語法

return code text;
return code URL;
return URL;

return 指令的語法由兩個或三個部分組成:

  • return: 關鍵字
  • code:http 狀態碼,當沒有設置 code 時,默認使用 302
  • text 或 URL:返回的字符串或跳轉的地址

使用範圍

  • server 節點
  • location 節點
  • if 塊中

  • 在 server 節點中的 return 的優先級要高於 location 節點的 return,不管 return 指令寫在 location 節點的上方還是下方
  • 在 return 指令中使用 code,經常會用到 301 或 302 ,區別如下:
    • 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,會跳轉到 c.com,不會被緩存

rewrite 指令

可以根據指定的正則表達式將用戶請求的 url 轉換成一個新的 url 進行重定向。

語法

rewrite regex replacement [flag];

return 指令的語法四個部分組成:

  • rewrite: 關鍵字
  • regex:正則表達式,用於匹配用戶請求的 url 地址
  • replacement:新的 url 地址,當地址開頭爲 http 或 https ,默認爲 302 重定向
  • flag:替換後的 url 根據 flag 進行處理,flag 有四個值
    • last:使用 replacement 的地址重新進行 location 匹配
    • break:會停止後面腳本的執行
    • redirect:返回 302 重定向,地址欄顯示重定向後的url
    • permanent:返回 301 重定向,地址欄顯示重定向後的url

使用範圍

  • server 節點
  • location 節點
  • if 塊中

  • rewrite 指令的適用範圍和 return 指令的是一致的,優先級也相同
  • 當 rewrite 指令和 return 指令同時存在時,如果 rewrite 最後的 flag 不是 break,會繼續執行 rewrite 之後的 return 指令
  • 沒有指定 flag 的情況下,默認爲 302 重定向

if 指令

通過 if 指令進行一些條件的判斷,然後進行 return、rewrite 或是其他的一些處理。

語法

if(condition){
}

使用範圍

  • server 節點
  • location 節點

if 判斷的一些規則

  • 變量和字符串做比較,使用 = 或 !=
  • 將變量和正則表達式做比較:
    • 大小寫敏感:~ 或 !~
    • 大小寫不敏感:~* 或 !~* ,例如上圖中的示例
  • 檢查文件是否存在,使用 -f 或 !-f
  • 檢查目錄是否存在,使用 -d 或 !-d

示例

下面以近期用到的兩個場景來演示實際的用法。

PC 端跳轉到移動端

場景描述:

  • PC 端發佈後的地址爲:192.168.0.1
  • 移動端採用 H5 開發,發佈後的地址:192.168.0.1:81
  • 在手機上訪問 PC 端地址,跳轉到移動端
  • PC 端和移動端使用同一個接口地址,接口地址是在 PC 端使用 /api 進行的代理
  • 只有頁面的請求跳轉到移動端,接口的請求不需要跳轉

配置如下:

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;
}
  • 兩個條件都滿足的情況下,進行跳轉
    • 設備類型爲移動端
    • 請求的路由中不包含 /api
  • 因爲 if 指令的條件的限制,不能再一個 condition 中使用多條件,所以定義了一個變量 $flag 來做判斷

將源地址中的特定參數傳遞到目標地址

場景描述:

  • 上面的示例中,跳轉到移動端後進入的是移動端的登錄頁面,因爲沒有登錄人的身份
  • 現在假設 PC 端的地址後有 authcode 的參數用來確定身份,除此之外還有其他的參數,例如:http://192.168.0.1?id=xxxxx&authcode=xxxxxxxx
  • 需要再跳轉後將 authcode 傳遞到移動端的地址後面,例如:http://192.168.0.1:81?authcode=xxxxxxxx 移動端可以做解析實現直接登錄

配置如下:

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