nginx?rewrite功能如何使用

    前言

    大家在瀏覽某些網站的時候,有沒有發現,當輸入: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指令

    該指令用來設置一個新的變量。

    nginx?rewrite功能如何使用

    • 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服務,然后瀏覽器訪問觀察下效果

    nginx?rewrite功能如何使用

    下面列舉了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; ????} }

    nginx?rewrite功能如何使用

    nginx?rewrite功能如何使用

    nginx?rewrite功能如何使用

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

    自定義日志輸出格式,將請求的日志輸出到自定義的日志中

    具體配置如下:

    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; ????????} ????}

    通過這種方式,就可以實現自定義請求的相關參數輸出到自定義的日志文件中

    nginx?rewrite功能如何使用

    if指令

    該指令用來支持條件判斷,并根據條件判斷結果選擇不同的Nginx配置

    nginx?rewrite功能如何使用

    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'; }

    nginx?rewrite功能如何使用

    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; ??}

    nginx?rewrite功能如何使用

    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?'<h2>not?find?file</h2>'; ????????????????} ????????}

    當訪問目錄下不存在的文件時,將會看到如下的異常返回

    nginx?rewrite功能如何使用

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

    • 當使用”-d”時,如果請求的目錄存在,if返回true,如果目錄不存在則返回false;

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

    使用”-e”和”!-e”來檢查所請求的目錄或文件是否存在

    • 當使用”-e”,如果請求的目錄或者文件存在時,if返回true,否則返回false;

    • 當使用”!-e”,如果請求的文件和文件所在路徑上的目錄都不存在返回true,否則返回false;

    7) 判斷請求的文件是否可執行使用”-x”和”!-x”

    • 當使用”-x”,如果請求的文件可執行,if返回true,否則返回false;

    • 當使用”!-x”,如果請求文件不可執行,返回true,否則返回false; break指令

    該指令用于中斷當前相同作用域中的其他Nginx配置。在Nginx的配置中,與該指令處于相同作用域的指令中,位于該指令之前的配置生效,位于之后的配置則無效

    nginx?rewrite功能如何使用

    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; ????????}

    nginx?rewrite功能如何使用

    return指令

    該指令用于完成對請求的處理,直接向客戶端返回響應狀態代碼。在return后的所有Nginx配置都是無效的

    nginx?rewrite功能如何使用

    • code,為返回給客戶端的HTTP狀態代理。可以返回的狀態代碼為0~999的任意HTTP狀態代理;

    • text:為返回給客戶端的響應體內容,支持變量的使用;

    • URL:為返回給客戶端的URL地址;

    location?/return?{ ????????????????default_type?application/json; ????????????????return?200?'{id:1,name:jike}'; ????????}

    nginx?rewrite功能如何使用

    rewrite指令

    該指令通過正則表達式的使用來改變URI。URL可以同時匹配并處理一個或多個指令,按照順序進行處理

    URL和URI的區別

    • URI:統一資源標識符

    • URL:統一資源定位符

    nginx?rewrite功能如何使用

    • Regex,用來匹配URI的正則表達式;

    • 替換:在匹配成功后,用于替換被截取字符串的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重寫日志的輸出功能

    nginx?rewrite功能如何使用

    開啟后,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文件配置下就可以了

    nginx?rewrite功能如何使用

    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,觀察效果

    nginx?rewrite功能如何使用

    nginx?rewrite功能如何使用

    nginx?rewrite功能如何使用

    nginx?rewrite功能如何使用

    二、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功能如何使用

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

    nginx?rewrite功能如何使用

    三、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; 	} }

    nginx?rewrite功能如何使用

    nginx?rewrite功能如何使用

    但是這個是非常不利于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; 	} }

    ? 版權聲明
    THE END
    喜歡就支持一下吧
    點贊12 分享