一 重定向概述
1.1 重定向介紹
重定向(Redirect)指通過各種方法將各種網絡請求重新定個方向轉到其它位置(如:網頁重定向、域名的重定向、路由選擇的變化也是對數據報文經由路徑的一種重定向)。
URL重寫是指通過配置conf文件,以讓網站的URL中達到某種狀態時則定向/跳轉到某個規則,比如常見的偽靜態、301重定向、瀏覽器定向等。當客戶端瀏覽某個網址時,將其訪問導向到另一個網址的技術。
其主要場景有如下兩個:
- 將一串很長的網址,轉成較短的網址,從而實現便於傳播、易於記憶。
- 調整或更換Web服務器,網址(域名)又必須要變更(如訪問目錄、訪問擴展名HTML變為PHP、訪問域名),為了能使舊的訪問依舊生效,從而實現自動重定向到新的網站。
1.2 類似概念
地址重寫:為了實現地址的標准化,如地址欄中中輸入 www.baidu.com. 也可以輸入 www.baidu.cn。最后都會被重寫到 www.baidu.com 上。瀏覽器的地址欄也會顯示www.baidu.com。即nginx把收到的客戶端的請求后把客戶端需要請求的內容所對應的服務器地址發給客戶端,讓客戶端自己去獲取,nginx同時返回302正確信息。
地址轉發:指在網絡數據傳輸過程中數據分組到達路由器或橋接器后,該設備通過檢查分組地址並將數據轉發到最近的局域網的過程。
反向代理:當瀏覽器訪問網站時,nginx反向代理服務器會代替客戶端向后端服務器查找所需的內容,然后nginx反向代理服務器會把查找的內容返回給客戶端。
地址重寫和地址轉發有以下不同點:
1. 地址重寫會改變瀏覽器中的地址,使之變成重寫成瀏覽器最新的地址。而地址轉發不會改變瀏覽器的地址的。
2. 地址重寫會產生兩次請求,而地址轉發只會有一次請求。
3. 地址轉發一般發生在同一站點項目內部,而地址重寫且不受限制。
4. 地址轉發的速度比地址重定向快。
注意:重定向和反向代理都可以實現Nginx的內容重定向。
1.3 重定向狀態碼
301:代表永久性轉移(Permanently Moved):舊地址A的資源已經被永久地移除了(這個資源不可訪問了),搜索引擎在抓取新內容的同時也將舊的網址交換為重定向之后的網址;
302:代表暫時性轉移(Temporarily Moved):舊地址A的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址。
301和302狀態碼都表示重定向,表示瀏覽器在拿到服務器返回的這個狀態碼后會自動跳轉到一個新的URL地址,這個地址可以從響應的Location首部中獲取(客戶端輸入的地址A瞬間變成了另一個地址B)。
1.4 涉及符號
- 正則表達式
1 ~ #表示匹配過程中區分大小寫; 2 ~* #表示匹配過程中不區分大小寫; 3 !~ #如果 '~' 匹配失敗時,那么該條件就為true; 4 !~* #如果 '~*' 匹配失敗時,那么該條件就為true。
示例01:
1 if ($http_user_agent ~ MSIE) { 2 …… 3 }
$http_user_agent值中是否含有 MSIE 字符串,如果包含則為true,否則為false。
注意:當表達式只是一個變量時,如果值為空或任何以0開頭的字符串都會當做false。
示例02:
1 if ( $http_user_agent ~* "(Android)|(iPhone)|(Mobile)|(WAP)|(UCWEB)" ){ 2 rewrite ^/$ http://www.cnblogs.com permanent; 3 }
解釋:
$http_user_agent值若為相應的手機訪問,則直接重定向至特定網頁。
- 文件匹配
1 -f #如果請求的文件存在,那么該條件為true; 2 !-f #如果該文件的目錄存在,該文件不存在,那么返回true。如果該文件和目錄都不存
在,請求的文件存在,也為false。
示例:
1 if (-f $request_filename) { 2 …… 3 }
解釋:判斷請求的文件是否存在
1 if (!-f $request_filename) { 2 …… 3 }
解釋:判斷請求的文件是否不存在
- 目錄匹配
1 -d #如果請求的目錄存在,則返回true。否則返回false; 2 !-d #如果請求的目錄不存在,但是該請求的上級目錄存在,則返回true。如果該上級目錄不存在,則返回false。 3 -e和!-e #用來判斷是否存在文件或目錄 4 -x和!-x #用來判斷文件是否可執行
- flag標記
1 last #表示完成rewrite,之后繼續向下匹配新的location URI規則,瀏覽器地址欄URL地址不變。 2 break #本條規則匹配完成后,終止匹配, 不再匹配后面的規則,完成重寫指令,瀏覽器地址欄URL地址不變。 3 redirect #返回302臨時重定向,瀏覽器地址會顯示跳轉新的URL地址。 4 permanent #返回301永久重定向,瀏覽器地址會顯示跳轉新的URL地址。
注意:last和break的區別參考配置示例09。
last一般寫在server和if中,而break一般使用在location中;
last不終止重寫后的url匹配,即新的url會再從server走一遍匹配流程,而break終止重寫后的匹配;
break和last都能阻止繼續執行后面的rewrite指令。
- 其他全局變量
1 $args #該變量中存放了請求URL中的請求指令,同$query_string; 2 $content_length #該變量中存放了HTTP請求頭中的Content-length字段。; 3 $content_type #該變量中存放了HTTP請求頭中的Content-type字段; 4 $document_root #該變量中存放了針對當前請求的根路徑。 5 $document_uri #該變量中存放了請求的當前URI, 但是不包括請求指令; 6 $host #變量中存放了請求的URL中的主機部分字段,如果請求中沒有Host行,則等於設置的服務器名; 7 $http_host #該變量與$host唯一區別帶有端口號; 8 $http_user_agent #該變量中存放客戶端的代理信息; 9 $http_cookie #該變量中存放客戶端的cookie信息。 10 $limit_rate #對連接速率的限制; 11 $request_method #請求的方法,比如"GET"、"POST"等; 12 $remote_addr #該變量中存放客戶端的地址; 13 $remote_port #該變量中存放了客戶端與服務器建立連接的端口號; 14 $remote_user #該變量中存放客戶端的用戶名,認證用; 15 $request_filename #該變量中存放了當前請求的資源文件的路徑名; 16 $request_body_file #該變量中存放了發給后端服務器的本地文件資源的名稱; 17 $request_method #該變量中存放了客戶端的請求方式,比如 'GET'、'POST'等。 18 $request_uri #該變量中存放了當前請求的URI,並且帶請求指令,即帶查詢字符串,不包含主機名,如:”/foo/bar.php?arg=baz”; 19 $query_string #與$args相同; 20 $scheme #該變量中存放了客戶端請求使用的協議,比如http或者是https; 21 $server_protocol #該變量中存放了客戶端請求協議的版本請求的協議版本,"HTTP/1.0"或"HTTP/1.1"; 22 $server_addr #服務器地址,如果沒有用listen指明服務器地址,使用這個變量將發起一次系統調用以取得地址(造成資源浪費); 23 $server_name #請求到達的服務器名; 24 $server_port #請求到達的服務器端口號; 25 $uri #請求的URI,可能和最初的值有不同,比如經過重定向之類的。
參數示例:
訪問鏈接是:http://demo.linuxds.com:88/test1/test2/test.php
網站路徑是:/var/www/html
1 $host:demo.linuxds.com 2 $server_port:88 3 $request_uri:http://demo.linuxds.com:88/test1/test2/test.php 4 $document_uri:/test1/test2/test.php 5 $document_root:/var/www/html 6 $request_filename:/var/www/html/test1/test2/test.php
1.5 return釋義
return一般用於對請求的客戶端直接返回響應狀態碼。在該作用域內return后面的所有nginx配置都是無效的。可以使用在server、location以及if配置中。除了支持跟狀態碼,還可以跟字符串或者url鏈接。
示例01:
1 server{ 2 listen 80; 3 server_name www.linuxds.com; 4 return 403; 5 rewrite /(.*) /abc/$1; #該行配置位於return后,則不會被執行。 6 }
示例02:
1 server { 2 ..... 3 4 if ($request_uri ~ "\.htpasswd|\.bak") 5 { 6 return 404; 7 rewrite /(.*) /aaa.txt; #該行配置位於return后,則不會被執行。 8 } 9 #如下為其他server,不受上一個server中的return影響,即若下面還有其他配置,會被執行。 10 ..... 11 }
示例03:
1 server{ 2 listen 80; 3 server_name www.linuxds.com; 4 return 200 "hello"; 5 }
說明:如果要想返回字符串,必須要加上狀態碼,否則會報錯。
示例04:
1 location ^~ /aming { 2 default_type application/json ; 3 return 200 '{"name":"xhy","id":"100"}'; 4 } #返回的字符串也支持json數據。
示例05:
1 location /test { 2 return 200 "$host $request_uri"; 3 } #返回的字符串也支持變量
示例06:
1 server{ 2 listen 80; 3 server_name www.linuxds.com; 4 return http://www.linuxds.com/123.html; 5 rewrite /(.*) /abc/$1; #該行配置位於return后,則不會被執行。 6 }
注意:return后面的url必須是以http://或者https://開頭的。
二 重定向配置
2.1 配置語法
語法:rewrite regex replacement [flag];;
默認值:——
可配置段:server, location
作用:通過正則表達式的使用來改變URI。可以同時存在一個或多個指令。需要按照順序依次對URL進行匹配和處理。
示例:
1 rewrite ^/(.*) http://www.baidu.com/$1 permanent;
解釋:
rewrite:固定關鍵字,表示開始進行rewrite匹配規則。
正則表達式^/(.*):正則表達式,匹配完整的域名和后面的路徑地址。
replacement為http://www.baidu.com/$1:其中$1是取regex部分()里面的內容。如果匹配成功后跳轉到的URL。
flag為permanent:代表永久重定向,即跳轉到 http://www.baidu.com/$1 地址上。
2.2 配置示例01
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite01.conf 2 server { 3 listen 80; 4 server_name cnblogs.linuxds.com; 5 access_log /var/log/nginx/cnblogs.access.log main; 6 error_log /var/log/nginx/cnblogs.error.log warn; 7 location / { 8 if ($host = 'cnblogs.linuxds.com') { 9 rewrite ^/(.*) http://www.cnblogs.com redirect; 10 } 11 } 12 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:結合if指令來對nginx請求進行判斷,若訪問http://cnblogs.linuxds.com,即$host = 'cnblogs.linuxds.com' 的時候,進行重定向跳轉,重定向至 http://www.cnblogs.com。
瀏覽測試:http://cnblogs.linuxds.com,訪問后會立刻跳轉。
2.2 配置示例02
1 [root@nginx01 ~]# mkdir /usr/share/nginx/file/ 2 [root@nginx01 ~]# echo '<h1>File</h1>' > /usr/share/nginx/file/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite02.conf 2 server { 3 listen 80; 4 server_name file.linuxds.com; 5 access_log /var/log/nginx/file.access.log main; 6 error_log /var/log/nginx/file.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/file; 9 if ( !-e $request_filename ) { 10 rewrite ^ http://www.cnblogs.com redirect; 11 } 12 } 13 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:結合if指令來對nginx請求進行判斷,若訪問http://file.linuxds.com的資源存在root目錄,則返回,若當前請求的資源文件不存在,則進行重定向跳轉,重定向至 http://www.cnblogs.com。
瀏覽測試:http://file.linuxds.com/index.html,進行測試。
訪問不存在的資源http://file.linuxds.com/aaaa,進行測試。
2.3 配置示例03
1 [root@nginx01 ~]# mkdir /usr/share/nginx/constant/ 2 [root@nginx01 ~]# echo '<h1>Constant</h1>' > /usr/share/nginx/constant/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite03.conf 2 server { 3 listen 80; 4 server_name constant.linuxds.com; 5 access_log /var/log/nginx/constant.access.log main; 6 error_log /var/log/nginx/constant.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/constant; 9 if ( !-e $request_filename ) { 10 rewrite ^ /itzgr/ break; 11 proxy_pass http://www.cnblogs.com; 12 } 13 } 14 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:結合if指令來對nginx請求進行判斷,若訪問http://constant.linuxds.com的資源存在root目錄,則返回,若當前請求的資源文件不存在,則進行重定向跳轉,重定向至http://www.cnblogs.com/itzgr。
瀏覽測試:訪問不存在的資源http://constant.linuxds.com/aaaa,進行測試。
2.4 配置示例04
1 [root@nginx01 ~]# mkdir /usr/share/nginx/last/ 2 [root@nginx01 ~]# echo '<h1>Last</h1>' > /usr/share/nginx/last/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite04.conf 2 server { 3 listen 80; 4 server_name last.linuxds.com; 5 access_log /var/log/nginx/last.access.log main; 6 error_log /var/log/nginx/last.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/last; 9 rewrite /last.html /index.html last; 10 } 11 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問 /last.html 的時候,頁面內容重寫到 /index.html 中。
瀏覽測試:瀏覽器訪問http://last.linuxds.com/。
瀏覽器訪問http://last.linuxds.com/last.html。
2.5 配置示例05
1 [root@nginx01 ~]# mkdir /usr/share/nginx/break/ 2 [root@nginx01 ~]# echo '<h1>Break</h1>' > /usr/share/nginx/break/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite05.conf 2 server { 3 listen 80; 4 server_name break.linuxds.com; 5 access_log /var/log/nginx/break.access.log main; 6 error_log /var/log/nginx/break.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/break; 9 rewrite /break.html /index.html break; 10 } 11 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問 /break.html 的時候,頁面內容重寫到 /index.html 中,並停止后續的匹配。
瀏覽測試:瀏覽器訪問http://break.linuxds.com/。
瀏覽器訪問http://break.linuxds.com/break.html。
2.6 配置示例06
1 [root@nginx01 ~]# mkdir /usr/share/nginx/rewrite/ 2 [root@nginx01 ~]# echo '<h1>Rewrite</h1>' > /usr/share/nginx/rewrite/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite06.conf 2 server { 3 listen 80; 4 server_name rewrite.linuxds.com; 5 access_log /var/log/nginx/rewrite.access.log main; 6 error_log /var/log/nginx/rewrite.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/rewrite; 9 rewrite /rewrite.html /index.html redirect; 10 } 11 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問 /redirect.html 的時候,頁面直接302定向到 /index.html中。
瀏覽測試:瀏覽器訪問http://rewrite.linuxds.com/。
瀏覽器訪問http://rewrite.linuxds.com/rewrite.html。
2.7 配置示例07
1 [root@nginx01 ~]# mkdir /usr/share/nginx/permanent/ 2 [root@nginx01 ~]# echo '<h1>Permanent</h1>' > /usr/share/nginx/permanent/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite07.conf 2 server { 3 listen 80; 4 server_name permanent.linuxds.com; 5 access_log /var/log/nginx/permanent.access.log main; 6 error_log /var/log/nginx/permanent.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/permanent; 9 rewrite /permanent.html /index.html permanent; 10 } 11 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問 /permanent.html 的時候,頁面直接301定向到 /index.html中。
瀏覽測試:瀏覽器訪問http://permanent.linuxds.com/。
瀏覽器訪問http://permanent.linuxds.com/permanent.html。
2.8 配置示例08
1 [root@nginx01 ~]# mkdir -p /usr/share/nginx/dirweb/dir 2 [root@nginx01 ~]# echo '<h1>Dirweb</h1>' > /usr/share/nginx/dirweb/dir/index.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite08.conf 2 server { 3 listen 80; 4 server_name dirweb.linuxds.com; 5 access_log /var/log/nginx/dirweb.access.log main; 6 error_log /var/log/nginx/dirweb.error.log warn; 7 location ~ .* { 8 root /usr/share/nginx/dirweb/; 9 rewrite ^/html/(.+?).html$ /dir/$1.html permanent; 10 } 11 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問 /html/*.html,頁面直接301定向到 /dir/*.html 中。
瀏覽測試:瀏覽器訪問http://dirweb.linuxds.com/dir/index.html。
瀏覽器訪問http://dirweb.linuxds.com/html/index.html。
2.9 配置示例09
1 [root@nginx01 ~]# mkdir -p /usr/share/nginx/lbreak 2 [root@nginx01 ~]# echo '<h1>Lbreak</h1>' > /usr/share/nginx/lbreak/index.html 3 [root@nginx01 ~]# echo '<h1>Test_Lbreak</h1>' > /usr/share/nginx/lbreak/test.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite09.conf 2 server { 3 listen 80; 4 server_name lbreak.linuxds.com; 5 access_log /var/log/nginx/lbreak.access.log main; 6 error_log /var/log/nginx/lbreak.error.log warn; 7 root /usr/share/nginx/lbreak/; 8 location / { 9 rewrite /last/ /test.html last; 10 rewrite /break/ /test.html break; 11 } 12 location = /test.html { 13 return http://www.cnblogs.com; 14 } 15 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問/last/時重寫到/test.html,然后使用新的uri再匹配,正好匹配到locatoin = /test.html然后返回http://www.cnblogs.com;
訪問/break時重寫到/test.html,由於返回了break,則直接停止了后續匹配,因此返回/test.html內容。
瀏覽測試:瀏覽器訪問http://lbreak.linuxds.com/last/。
瀏覽器訪問http://lbreak.linuxds.com/break/。
2.10 配置示例10
1 [root@nginx01 ~]# mkdir -p /usr/share/nginx/admin/xhy 2 [root@nginx01 ~]# echo '<h1>Admin</h1>' > /usr/share/nginx/admin/admin.html
1 [root@nginx01 ~]# vi /etc/nginx/conf.d/rewrite10.conf 2 server { 3 listen 80; 4 server_name admin.linuxds.com; 5 access_log /var/log/nginx/admin.access.log main; 6 error_log /var/log/nginx/admin.error.log warn; 7 root /usr/share/nginx/admin/; 8 location / { 9 rewrite /xhyadmin.html /admin.html break; 10 } 11 location /admin.html { 12 return 403; 13 } 14 }
1 [root@nginx01 ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置文件 2 [root@nginx01 ~]# nginx -s reload #重載配置文件
配置解釋:訪問http://admin.linuxds.com/admin.html時直接返回無權限的403代碼,必須通過http://admin.linuxds.com/xhyadmin.html來進行訪問,即訪問/xhyadmin.html重寫到/admin.html,但不能直接訪問/admin.html,可應用於隱藏真實地址。
瀏覽測試:http://admin.linuxds.com/admin.html。
瀏覽器訪問http://admin.linuxds.com/xhyadmin.html。
三 其他簡略配置
1 # 如果文件不存在則返回400 2 if (!-f $request_filename) { 3 return 400; 4 }
1 # 如果host不是demo.linuxds.com,則301到www.baidu.com中 2 if ( $host != 'demo.linuxds.com' ){ 3 rewrite ^/(.*)$ https://www.baidu.com/$1 permanent; 4 }
1 # 如果請求類型不是POST則返回405 2 if ($request_method = POST) { 3 return 405; 4 }
1 # 如果參數中有 a=1 則301到demo.linuxds.com 2 if ($args ~ a=1) { 3 rewrite ^ http://demo.linuxds.com/ permanent; 4 }
1 # 如果客戶使用IE瀏覽器訪問,則重定向到/nginx-ie目錄下: 2 if ($http_user_agent ~ MSIE) { 3 rewrite ^(.*)$ /nginx-ie/$1 break; 4 }
1 # 多目錄重定向為參數的形式。 2 # 將xhy.linuxds.com/images/girl 重定向為 xhy.linuxds.com/index.php?act=images&name=xhy&id=girl參數的形式。 3 if ($host ~* (.*)\.domain\.com) { 4 set $sub_name $1; 5 rewrite ^/images\/(\d+)\/?$ /index.php?act=images&cid=$sub_name&id=$1 last; 6 }
1 # 將目錄對調,/images/girl -> /girl?id=images。 2 rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
1 # 目錄通過重定向自動追加/ 2 if (-d $request_filename){ 3 rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; 4 }
1 # 簡單域名重定向 2 server 3 { 4 listen 80; 5 server_name xhy.linuxds.com; 6 index index.html index.htm index.php; 7 root /usr/share/nginx/xhy/; 8 rewrite ^/ http://www.cnblogs.com; 9 access_log off; 10 } 11 server { 12 listen 80; 13 server_name linuxds.com www.linuxds.com; 14 if ($host != 'www.linuxds.com' ) { 15 rewrite ^/(.*)$ http://www.linuxds.com/$1 permanent; 16 } 17 }
1 # 指定域名重定向 2 server_name xhy.linuxds.com xhy.linuxds.cn; 3 index index.html index.htm index.php; 4 root /usr/share/nginx/xhy/; 5 if ($host ~ "linuxds\.cn") { 6 rewrite ^(.*) http://xhy.linuxds.com$1/ permanent; 7 }
1 # 多域名重定向 2 server_name xhy.linuxds.com xhy.linuxds.cn xhy.linuxds.net; 3 index index.html index.htm index.php; 4 root /usr/share/nginx/xhy/; 5 if ($host !~ "linuxds\.com") { 6 rewrite ^(.*) http://xhy.linuxds.com/$1 permanent; 7 }
1 # 三級域名跳轉。 2 if ($http_host ~* "^(.*)\.i\.linuxds\.com$") { 3 rewrite ^(.*) http://xhy.linuxds.com$1/; 4 break; 5 }
1 # 域名鏡像 2 server 3 { 4 listen 80; 5 server_name mirror.linuxds.com; 6 index index.html index.htm index.php; 7 root /usr/share/nginx/xhy/; 8 rewrite ^/(.*) http://xhy.linuxds.com/$1 last; 9 access_log off; 10 }