首頁 > 軟體

nginx rewrite功能使用場景分析

2022-05-26 18:04:33

前言

大家在瀏覽某些網站的時候,有沒有發現,當輸入:www.abc.com或者www.abcd.com的時候,頁面均能正常顯示www.abc.com的主頁內容。這就是nginx rewrite的一個使用場景。

rewrite簡介

rewrite是Nginx伺服器提供的一個重要基本功能,主要作用用來實現URL地址重寫

rewrite功能實現依賴於pcre的支援,因此在編譯安裝Nginx伺服器之前,需安裝pcre庫(nginx使用ngx_http_rewrite_module模組來解析和處理Rewrite功能的相關設定)

在真正瞭解rewrite的使用之前,有必要全面系統學習下rewrite相關的指令和語法使用,下面來逐一瞭解下吧

Rewrite規則與指令

set指令

該指令用來設定一個新的變數。

  • variable,變數名,該變數名要用"$"作為變數的第一個字元,且不能與Nginx伺服器預設的全域性變數同名;
  • value:變數值,可以是字串、其他變數或者變數的組合等;

一個簡單的案例

server {
    listen 8081;
    server_name localhsot;
    location /server {
            set $name zhangsan;
            set $age 19;
            default_type text/plain;
            return 200 $name=$age;
    }
}

重啟nginx服務,然後瀏覽器存取觀察下效果

下面列舉了Rewrite常用全域性變數

這些變數可以在使用過程中結合自身的業務靈活選擇使用

變數說明
$args變數中存放了請求URL中的請求指令。如http://IP:8080?arg1=value1&args2=value2中 的"arg1=value1&arg2=value2",功能和$query_string一樣
$http_user_agent變數儲存了使用者存取服務的代理資訊(如果通過瀏覽器存取,記錄的是瀏覽器的相關版本資訊)
$host變數儲存的是存取伺服器的server_name值
$document_uri變數儲存了當前存取地址的URI。比如http://IP/server?id=10&name=zhangsan中的"/server",功能和$uri一樣
$document_root變數儲存的是當前請求對應location的root值,如果未設定,預設指向Nginx自帶html目錄所在位置
$content_length變數儲存的是請求頭中的Content-Length的值
$content_type變數儲存的是請求頭中的Content-Type的值
$http_cookie變數儲存的是使用者端的cookie資訊,可以通過add_header Set-Cookie’cookieName=cookieValue’來新增cookie數 據
$limit_rate變數中儲存的是Nginx伺服器對網路連線速率的限制,也就是Nginx設定中對limit_rate指令設定的值,預設是0,不限制
$remote_addr變數中儲存的是使用者端的IP地址
$remote_port變數中儲存了使用者端與伺服器端建立連線的埠號
$remote_user變數中儲存了使用者端的使用者名稱,需要有認證模組才能獲取
$scheme變數中儲存了存取協定
$server_addr變數中儲存了伺服器端的地址
$server_name變數中儲存了使用者端請求到達的伺服器的名稱
$server_port變數中儲存了使用者端請求到達伺服器的埠號
$server_protocol變數中儲存了使用者端請求協定的版本,比如"HTTP/1.1"
$request_body_file變數中儲存了發給後端伺服器的本地檔案資源的名稱
$request_method變數中儲存了使用者端的請求方式,比如"GET","POST"等
$request_filename變數中儲存了當前請求的資原始檔的路徑名
$request_uri變數中儲存了當前請求的URI,並且攜帶請求引數,比如http://IP/server?id=10&name=zhangsan中的"/server?id=10&name=zhangsan名

我們來隨機測試下幾個指令的使用吧

$args

server {
    listen 8081;
    server_name localhsot;
    location /server {
            set $name zhangsan;
            set $age 19;
            default_type text/plain;
            return 200 $name=$age=$args;
    }
}

$http_user_agent

其他的指令有興趣的同學可以自行嘗試,下面使用這些指令完成一個需求

自定義紀錄檔輸出格式,將請求的紀錄檔輸出到自定義的紀錄檔中

具體設定如下:

log_format main '$remote_addr - $request - $status - $request_uri - $http_user_agent';
   server {
        listen 8081;
        server_name localhsot;
        location /server {
                access_log logs/access-server.log main;
                set $name zhangsan;
                set $age 19;
                default_type text/plain;
                return 200 $name=$age=$args=$http_user_agent;
        }
    }

通過這種方式,就可以實現自定義請求的相關引數輸出到自定義的紀錄檔檔案中

if指令

該指令用來支援條件判斷,並根據條件判斷結果選擇不同的Nginx設定

condition為判定條件,可以支援以下寫法:

1)變數名稱,如果變數名對應的值為空或者是0,if都判斷為false,其他條件為true

if ($param) { 

} 
location /testif {
                set $username 'zhangsan';
                default_type text/plain;
                if ($username){
                        return 200 success;
                }
                return 200 'params is empty';
}

2) 使用"=“和”!="比較變數和字串是否相等,滿足為true,不滿足為false

if ($request_method = POST) { 
 return 405; 3
}

注意:此處和Java不一樣的是字串不需加引號

3)使用正規表示式對變數匹配

  • 匹配成功返回true,否則返回false;
  • 變數與正規表示式之間使用"“,”“,”!“,”!"來連線;
  • “~” 代表匹配正規表示式過程中區分大小寫;
  • "~*"代表匹配正規表示式過程中不區分大小寫;
  • "!“和”!*"剛好和上面取相反值,如果匹配上返回false,匹配不上返回true;
if ($http_user_agent ~ MSIE) {
    #$http_user_agent的值中是否包含MSIE字串,如果包含返回 true 
}

注意:正規表示式字串一般不需要加引號,但是如果字串中包含"}“或者是”;"等字元時,就需要把引號加上

if ($http_user_agent ~ Safari){
                        return 200 Chrome;
  }

4)判斷請求檔案是否存在使用"-f"和"!-f"

  • 當使用"-f"時,如果請求的檔案存在返回true,不存在返回false;
  • 當使用"!f"時,如果請求檔案不存在,但該檔案所在目錄存在返回true,檔案和目錄都不存在返回false,如果檔案存在返回false;
if (-f $request_filename){
    #判斷請求的檔案是否存在
}

if (!-f $request_filename){
    #判斷請求的檔案是否不存在
}

案例展示

location /file {
                root html;
                default_type text/html;
                if (!-f $request_filename){
                        return 200 '<h1>not find file</h1>';
                }
        }

當存取目錄下不存在的檔案時,將會看到如下的異常返回

5) 判斷請求的目錄是否存在使用"-d"和"!-d"

  • 當使用"-d"時,如果請求的目錄存在,if返回true,如果目錄不存在則返回false;
  • 當使用"!-d"時,如果請求的目錄不存在但該目錄的上級目錄存在則返回true,該目錄和它上級目錄都不存在則返回false,如果請求目錄存在也返回false;

6) 判斷請求的目錄或者檔案是否存在使用"-e"和"!-e"

  • 當使用"-e",如果請求的目錄或者檔案存在時,if返回true,否則返回false;
  • 當使用"!-e",如果請求的檔案和檔案所在路徑上的目錄都不存在返回true,否則返回false;

7) 判斷請求的檔案是否可執行使用"-x"和"!-x"

  • 當使用"-x",如果請求的檔案可執行,if返回true,否則返回false;
  • 當使用"!-x",如果請求檔案不可執行,返回true,否則返回false; break指令

該指令用於中斷當前相同作用域中的其他Nginx設定。與該指令處於同一作用域的Nginx設定中,位於它前面的指令設定生效,位於後面的指令設定無效

location /{
    if ($param){

        set $id $1;
        break;
        limit_rate 10k;
    }
}

案例演示

location /break {
                default_type text/plain;
                set $username MIKE;
                if ($args){
                        set $username JIM;
                        break;
                        set $username JODAN;
                }
                return 200 $username;
        }

return指令

該指令用於完成對請求的處理,直接向用戶端返回響應狀態程式碼。在return後的所有Nginx設定都是無效的

  • code,為返回給使用者端的HTTP狀態代理。可以返回的狀態程式碼為0~999的任意HTTP狀態代理;
  • text:為返回給使用者端的響應體內容,支援變數的使用;
  • URL:為返回給使用者端的URL地址;
location /return {
                default_type application/json;
                return 200 '{id:1,name:jike}';
        }

rewrite指令

該指令通過正規表示式的使用來改變URI。可以同時存在一個或者多個指令,按照順序依次對URL進行匹配和處理

URL和URI的區別

  • URI:統一資源識別符號
  • URL:統一資源定位符

  • regex,用來匹配URI的正規表示式;
  • replacement:匹配成功後,用於替換URI中被擷取內容的字串。如果該字串是以"http://"或者"https://"開頭的,則不會繼續向下對URI進行其他處理,而是直接返回重寫後的URI給使用者端;
  • flag:用來設定rewrite對URI的處理行為,可選值有如下

last break redirect permanent

last : 終止繼續在本location中處理接收到的URI,並將此處重寫的URI作為一個新的URI,使用各location塊進行處理。該標誌將重寫的URI重寫在server塊中執行,為重寫後的URI提供了轉入到其他location塊的機會;

break : 將此處重寫的URI作為一個新的URI,在本塊中繼續處理,該標誌重寫後的地址在當前的location塊中執行,不會將新的URI轉向其他的location塊;

redirect : 將重寫後的URI返回給使用者端,狀態碼為302,指明是臨時重定向URI,主要用在replacement變數不是以 “http://”或“https://”開頭的情況;

redirect : 將重寫後的URI返回給使用者端,狀態碼為302,指明是臨時重定向URI,主要用在replacement變數不是以 “http://”或“https://”開頭的情況;

permanent : 將重寫後的URI返回給使用者端,狀態碼為301,指明是臨時重定向URI,主要用在replacement變數不是以 “http://”或“https://”開頭的情況;

範例1

location /rewirte {
                rewrite ^/rewrite/urlw*$ https://www.baidu.com;
                rewrite ^/rewrite/(test)/w*$ /$1;
                rewrite ^/rewrite/(hello)/w*$ /$1;
        }
        location /test {
                default_type text/plain;
                return 200 "hello success";
        }

範例2

location /rewirte {
                rewrite ^/rewrite/urlw*$ https://www.baidu.com;
                rewrite ^/rewrite/(test)/w*$ /$1 last;
                rewrite ^/rewrite/(hello)/w*$ /$1 last;
        }
        location /test {
                default_type text/plain;
                return 200 "hello success";
        }

rewrite_log指令

該指令設定是否開啟URL重寫紀錄檔的輸出功能

開啟後,URL重寫的相關紀錄檔將以notice級別輸出到error_log指令設定的紀錄檔檔案彙總

location /rewirte {
				rewrite_log on;
				error_log logs/error.log notice;
                rewrite ^/rewrite/urlw*$ https://www.baidu.com;
                rewrite ^/rewrite/(test)/w*$ /$1 last;
                rewrite ^/rewrite/(hello)/w*$ /$1 last;
        }

一、rewrite設定域名跳轉

有很多大型網站,在起步的時候,比如域名為 : www.haoyijia.com,但是域名太長所帶來的問題就是不方便記憶,於是後面改成 www.hyj.com,問題是,一些老使用者之前一直習慣了那個長域名,如何在老使用者輸入長域名的時候仍然可以跳轉到新的短域名上呢?就可以考慮使用rewrite的功能;下面在本地做一下模擬。

設定步驟:

1、準備兩個域名

這裡我直接在本地模擬2個域名,通過在原生的hosts檔案設定下就可以了

2、設定nginx.conf檔案

server {

		listen 80;
		server_name www.zcy.com www.zhangcongyi.com;
		rewrite ^/ http://www.jd.com permanent;
	}

重啟nginx服務,瀏覽器存取:www.zcy.com 或者www.zhangcongyi.com,觀察效果

二、rewrite設定獨立域名

一個完整的專案包含多個模組,比如購物網站有商品商品搜尋模組、商品詳情模組、購物車模組等,那麼我們如何為每一個模組設定獨立的域名。

server{
		listen 80;
		server_name search.hm.com;
		rewrite ^(.*) http://www.hm.com/bbs$1 last;
	}
	server{
		listen 81;
		server_name item.hm.com;
		rewrite ^(.*) http://www.hm.com/item$1 last;
	}
	server{
		listen 82;
		server_name cart.hm.com;
		rewrite ^(.*) http://www.hm.com/cart$1 last;
	}

原生的hosts檔案新增如下設定

重啟nginx服務,可以在瀏覽器存取下觀察效果如何

三、rewrite設定目錄合併

搜尋引擎優化(SEO)是一種利用搜尋引擎的搜尋規則,來提供目的網站的有關搜尋引擎內排名的方式;

我們在建立自己的站點時,可以通過很多種方式有效提供搜尋引擎優化的程度,其中有一項就包含URL的目錄層級一般不要超過三層,否則的話不利於搜尋引擎的搜尋也給使用者端的輸入帶來了負擔;

但是將所有的檔案放在一個目錄下又會導致檔案資源管理混亂,並且存取檔案的速度也會隨著檔案增多而慢下來,這兩個問題是相互矛盾的,使用rewrite就可以解決上述問題;

舉例,網站中有一個資原始檔的存取路徑時,比如存取:/server/11/22/33/44/20.html,也就是說20.html存在於第5級目錄下,如果想要存取該資原始檔,使用者端的URL地址就要寫成http://www.web.name/server/11/22/33/44/20.html

server {
	listen 80;
	server_name www.web.com;
	location /server{
		root html;
	}
}

但是這個是非常不利於SEO搜尋引擎優化的,同時使用者端也不好記,使用rewrite我們可以進行如下設定:

server {
	listen 80;
	server_name www.web.com;
	location /server{
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)- ([0-9]+).html$ /server/$1/$2/$3/$4/$5.html last;
	}
}

到此這篇關於nginx rewrite功能使用的文章就介紹到這了,更多相關nginx rewrite使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com