nginx編譯的時候默認是把rewrite功能編輯進去的,但是因為rewrite需要使用正則表達式,因此需要安裝pcre依賴包。
yum install -y pcre pcre-install
rewrite是nginx服務器提供的一個重要基本功能,其再web服務器產品中幾乎是必備的,用於實現URL的重寫。URL重寫是非常有用的功能,比如它可以讓我們在改變網站結構后,不需要要求客戶端用戶修改原來的書簽,業無需其他網站修改對我們網站的友情鏈接;它還可以在一定程度上提高網站的安全性。
地址重定向與地址轉發
地址重定向:是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址.所以地址欄顯示的是新的URL。比如在瀏覽器輸入baidu.com時,瀏覽器會自動跳到https://www.baidu.com這個過程,就是一個地址重定向。我們輸入的是baidu.com,但是瀏覽器顯示的URL是服務器返回的一個新的URL地址。
地址轉發:是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然后把這些內容再發給瀏覽器.瀏覽器根本不知道服務器發送的內容從哪里來的,因為這個跳轉過程實在服務器實現的,並不是在客戶端實現的所以客戶端並不知道這個跳轉動作,所以它的地址欄還是原來的地址。
轉發是服務器行為,重定向是客戶端行為。
地址重定向與地址轉發的異同:
- 地址轉發后,客戶端瀏覽器中地址欄顯示是不改變的;而地址重寫后客戶端地址瀏覽器地址欄中地址改變為服務器選擇確定的地址。
- 在一次地址轉發過程中,客戶端只產生一次網絡請求;而一次地址重寫一般會產生兩次網絡請求。
- 地址轉發一般發生在同一站點內;地址重定向沒有限制。
- 地址轉發到的頁面可以不用全路徑名表示,而地址重寫到的頁面必須使用完整的路徑名表示。
- 地址轉發過程中,可以將客戶端請求request范圍內屬性傳遞給新的頁面,但地址重定向不可以。
- 地址轉發要比地址重定向快。
https://www.cnblogs.com/he-px/p/7448603.html 這片博文說明了地址轉發與地址重定向的一些解釋!
rewrite規則
rewrite規則是學習和使用nginx服務器rewrite功能的基礎,可以借助於pcre實現uri的重定向,並且它還支持nginx預設變量。
廢話不說,來介紹有關rewrite的指令:
if指令
該指令用來支持條件判斷,並根據條件判斷的結果選擇不同的nginx配置,可以在server塊或者location塊中配置該指令。
if (condition) {....}
#花括號代表一個作用域,形成一個if塊,是條件為真時的nginx配置。condition為判斷條件,有以下幾種寫法。
- 變量名。如果變量的值為空字符串或者以“0”開頭的任意字符串,if指令認為條件為false,其他條件為true:
if ($document_uri) { return http://10.0.102.204$document_uri; }
#如果請求中有uri,則返回一個指定的url;事實上所有發往本機的請求都會返回這個url,因為http://localhost也是含有一個URI的,可省略的“/”;測試的時候是這樣
- 使用“=”和“!=”比較變量和字符串是否相等,相等時if指令認為條件為true,反之為false。
if ($remote_addr = 172.16.100.19) { return 403; }
#若是客戶端ip為172.16.100.19,則禁止訪問,返回403代碼。
#需要注意的是這里的字符串不需要加引號!
- 使用正則表達式對變量進行匹配,成功為true,否則為false。變量與正則表達式之間用"~","~*","!~"或"!~*"連接。
- ~:表示匹配過程中對大小寫敏感。
- ~*:匹配過程中對大小寫不敏感。
- !~和!~*: 前面的感嘆號表示匹配失敗時結果為true,否則為false。
在正則表達式中,可以使用小括號對變量進行截取,在花括號中引用$1....$9引用截取的值。
if ($remote_addr ~ 10.0.102.*) { return 403; }
#以上102網段的所有機器均不能訪問。
#使用小括號對正則表達式的截取,遇見的話補上,可以類比Python中正則截取,規則都一樣!
- 判斷文件是否存在用-f,判斷目錄是否存在用-d,判斷請求的目錄或者文件是否存在用-e,判斷請求的文件是否有可執行權限用-x;以上的判斷存在則條件為真,若是在前面加上"!"則表示非的意思!
location /one.html { if (-f $request_filename) { return http://10.0.102.204$document_uri; }
#若是請求的文件存在,則轉向另一個網址發起請求。這里request_filename變量是文件在服務器上的絕對路徑。
#譬如這里,因為root路徑默認是/usr/local/nginx/html,因此request_filename的路徑為/usr/local/nginx/html/one.html.
break指令與return指令
- break指令用於中斷當前同一作用域中的nginx配置。與該指令處於同一作用域的nginx配置中,位於它前面的指令配置生效,位於后面的指令配置無效。nginx服務器在根據配置處理請求的過程中遇到該指令時,回到上一層作用域繼續向下讀取配置。可以用作server塊和location塊。
location / { if ($slow) { set $id $1 #處於break之前,配置有效 break; limit_rete 100k; #處於break指令之后,配置無效 } ..... #其他nginx配置指令,處於break作用域的上一層,配置有效 }
- return指令,該指令用於完成對請求的處理,直接向客戶端返回響應的狀態碼。處於該指令后所有的nginx配置指令無效。可以在server塊和if塊中使用。
return [text];
return code URL;
return URL;
#code,返回給客戶端的狀態碼。可以返回的狀態碼為0~999的任意http狀態碼。非標准的444狀態碼可以強制關閉服務端與客戶端的連接而不返回任何響應信息。
#text,為返回給客戶端的響應具體內容,支持變量的使用。
#URL,返回給客戶端URL地址。
code的幾種狀態說明:
301: 表示被請求資源永久移動到新的位置。
302:表示臨時重定向,要求使用GET請求。
303:表對當前請求的響應可以在另一個URL上找到,並且客戶端當采用GET方式訪問那個資源。
307:請求的資源臨時從不同的URL響應。
return指令的用法,在上面if語句中已經使用,不再說明。
rewrite指令
該指令通過正則表達式的使用來改變URI。可以同時存在一個或者多個,安裝順序依次對URI進行匹配和處理。
該指令可以在server塊或者Location塊中配置,其語法結構為:
rewrite regex replacement [flag];
#regx,用於匹配URI的正則表達式。使用括號標記要截取的內容。
#replacement,匹配成功后用於替換uri中被截取內容的字符串。默認情況下,如果該字符串是由"http://"或者"hppts://"開頭的,則不會繼續向下對uri進行處理,而直接將重寫后的URI返回給客戶端。
#flag,用來設置rewrite對URI的處理行為,可以為以下標記中的一個。
- last,終止繼續在本Location塊中處理接收到的URI,並將重寫的URI作為一個新的URI,使用各Location塊進行處理。該標志將重寫后的URI重新在server塊中執行,為重寫后的URI提供了轉入到其他Location塊的機會。
- break,將此處重寫的URI作為一個新的URI,在本塊中繼續執行。但是不會將新的URI轉向到其他Location塊。
- redirect,將重寫后的URI返回給客戶端,狀態碼為302,指明是臨時重定向URI,主要用在replacement變量不是以"http://"和"hpps://"開頭的情況下。
- permanent,將重寫后的URI返回給客戶端,狀態碼為301,指明是永久重定向。
需要特別注意rewrite接收到的uri不包含host地址。因此regex不可能匹配到uri的host地址。
另外客戶端使用get發起請求時,請求后面的參數指令也不包含在rewrite指令接受到的內容中。但是若想在replacement中引用參數,可以使用nginx全局變量$requext_uri,但是在使用的時候需要加上一個"?".
rewrite regex http://wwww.xxx.com$requext_uri? permanect;
rewrite_log指令
該指令配置是否開啟URL重寫日志輸出功能,其語法結構為:
rewirte_log on | off;
默認設置為off。如果配置開啟,url重寫日志將以notice級別輸出到error_log指令配置的日志文件中。
set指令
該指令用於設置一個新的變量。
set variable value;
#variable,為變量名稱。注意要用符號$作為變量的第一個字符,變量不能與nginx服務器預設的全局變量同名。
#value,為變量的值,可以使字符串,其他變量或變量的組合等
uninitialized_variable_warn指令
該指令用於配置使用未初始化的變量時,是否記錄警告日志。
uninitialized_variable_warn on | off;
默認設置開啟狀態。
nginx服務器預設的全局變量如下,可能不太全。
變量 說明
$args 存放了請求url中的請求指令。比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的arg1=value1&arg2=value2
$content_length 存放請求頭中的Content-length字段
$content_type 存放了請求頭中的Content-type字段
$document_root 存放了針對當前請求的根路徑
$document_uri 請求中的uri,不包含請求指令 ,比如比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的/server/source
$host 存放了請求url中的主機字段,比如比如http://www.myweb.name/server/source?arg1=value1&arg2=value2中的www.myweb.name。如果請求中的主機部分字段不可用或者為空,則存放nginx配置中該server塊中server_name指令的配置值
$http_user_agent 存放客戶端的代理
$http_cookie cookie
$limit_rate nginx配置中limit_rate指令的配置值
$remote_addr 客戶端的地址
$remote_port 客戶端與服務器端建立連接的端口號
$remote_user 變量中存放了客戶端的用戶名
$request_body_file 存放了發給后端服務器的本地文件資源的名稱
$request_method 存放了客戶端的請求方式,如get,post等
$request_filename 存放當前請求的資源文件的路徑名
$requset_uri 當前請求的uri,並且帶有指令
$query_string $args含義相同
$scheme 客戶端請求使用的協議,如http,https,ftp等
$server_protocol 客戶端請求協議的版本,如”HTTP/1.0”,”HTTP/1.1”
$server_addr 服務器的地址
$server_name 客戶端請求到達的服務器的名稱
$server_port 客戶端請求到達的服務器的端口號
$uri 同 $document_uri