快速掌握Nginx(二) —— Nginx的Location和Rewrite

1 location詳解

1.location匹配規則

  Nginx中location的做用是根據Url來決定怎麼處理用戶請求(轉發請求給其餘服務器處理或者查找本地文件進行處理)。location支持正則表達式,配置十分靈活。咱們能夠在一個虛擬主機(nginx中的一個server節點)下配置多個location以知足如動靜分離,防盜鏈等需求。php

  location語法是: location [=|~|~*|^~]  /uri/ {… },具體解釋以下表:css

符號html

含義nginx

location  =    /urlweb

=   :開頭,表示精確匹配,uri必須徹底一致才能匹配成功正則表達式

location  ^~ /Purlchrome

^~:Puri和請求url的開頭相同就匹配成功,且再也不去匹配正則,也屬於普通匹配segmentfault

location        /Purl後端

普通匹配,Purl和用戶請求url的開頭相同就匹配成功,若是有多個普通匹配都匹配成功則按最長的 。瀏覽器

  若有location /static/,和oaction /static/img/  當請求是www.mysite.com/static/img/1.jpg時,第二個location匹配的更長,因此和第二個loaction匹配成功。

location   ~   reg

~  :區分大小寫的正則匹配

location  ~*  reg

~* :不區分大小寫的正則匹配

location的匹配順序是: = /url   >   ^~ /Purl   > /Purl   >  ~ 和 ~* ,具體流程以下圖所示,須要注意:通常狀況下,匹配成功了普通字符串location後還會進行正則表達式location匹配。兩種狀況除外:①使用「=」,即精準匹配,若是匹配成功就當即中止其餘匹配;②使用「^~」前綴,這個前綴告訴nginx ,若是匹配成功再也不進行正則匹配。

簡單總結:

1.  先進行精準匹配,若是匹配成功,當即返回結果並結束匹配過程。

2.  進行普通匹配,若是有多個location匹配成功,將「最長前綴」的location做爲臨時結果(若是是 ^~類型的普通匹配成功則直接返回結果,結束匹配過程)。

3.  由上至下逐一進行正則匹配,一旦匹配成功1個,當即返回結果,並結束解析過程;若是沒有一個正則匹配成功,那麼將普通匹配的最長前綴location做爲最終結果返回,並結束匹配過程。

2. 實際使用建議

實際使用中,我的以爲每一個虛擬主機下(server節點下)至少有三個匹配規則定義,以下:
#直接匹配網站根,經過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。
#這裏是直接轉發給後端應用服務器了,也能夠是一個靜態首頁
# 第一個必選規則
location = / {
    proxy_pass http://tomcat:8080/index
}
# 第二個必選規則是處理靜態文件請求,這是nginx做爲http服務器的強項
# 有兩種配置模式,目錄匹配或後綴匹配,任選其一或搭配使用
location ^~ /static/ {
    root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
}
#第三個規則就是通用規則,用來轉發動態請求到後端應用服務器
#非靜態文件請求就默認是動態請求,本身根據實際把握
#畢竟目前的一些框架的流行,帶.php,.jsp後綴的狀況不多了
location / {
    proxy_pass http://tomcat:8080/
}

實際使用建議參考自:http://www.javashuo.com/article/p-rfvnylnv-z.html

2 rewrite詳解

1 rewrite簡單認識

  rewrite模塊即ngx_http_rewrite_module模塊,主要功能是實現URI重定向。rewrite模塊會經過正則匹配重寫URI,而後內部跳轉再匹配location,或者直接作30x重定向返回客戶端。Nginx的rewrite功能須要PCRE的支持,PCRE是perl兼容正則表達式庫。rewrite指令的語法十分簡單以下:

 rewrite將符合正則的內容替換爲新的替代內容
rewrite <regex> <replacement>
[flag]; 關鍵字 正則 替代內容 flag標記 正 則: perl兼容正則表達式語句進行規則匹配 替代內容: 將正則匹配的內容替換成replacement flag標記: rewrite支持的flag標記 ------------------------------------------------------------------------------- flag標記說明: last #匹配完成後再也不匹配當前環境下的其餘rewrite指令,開始匹配新的location URI規則 break #匹配完成即終止,再也不匹配後面的任何規則 redirect #返回302臨時重定向,瀏覽器地址會顯示跳轉後的URL地址 permanent #返回301永久重定向,瀏覽器地址欄會顯示跳轉後的URL地址

使用rewrite時也會用到,幾個經常使用的指令彙總以下:

指令

使用範圍

做用

if ( condition ){ // 符合條件執行}

location,server

條件判斷。

=     !=  判斷是否相等

~     ~* 判斷是否符合正則

-e    !-e 判斷文件,目錄,符號連接是否存在

-d    !-d 判斷目錄是否存在

-f     !-f 判斷文件是否存在

-x    !-x 判斷是否可執行

break

server,location,if

再也不繼續執行任何指令,直接退出規則的執行

return 

server,location,if

結束規則的執行和返回狀態碼給客戶端;如 return 403;

set  variable  ‘value’

 http,server,location,if

 新建變量,並賦值 ;如 set varx 'hello'

  

   一個簡單的栗子,簡單瞭解下rewrite:

server{
        listen 80;
        server_name www.mysite.com;
        #在server中調轉到 愛奇藝
        #rewrite ^/(.*) https://www.iqiyi.com break;
        location = /{
                #location中跳轉到百度
                rewrite ^/(.*) http://www.baidu.com;
                root html;
                index index.html;
        }
        #日誌記錄
        error_log logs/mysite.error.log error;
        access_log  logs/mysite.access.log  main;
}       

  咱們知道默認狀況訪問nginx的虛擬主機會展現nginx的歡迎界面,咱們經過rewrite指令跳轉到百度。輸入虛擬機的IP,訪問結果再也不是nginx歡迎頁,而是302跳轉到百度以下:

 2 rewrite的執行過程

  nginx中咱們能夠有多個rewrite指令,默認狀況下rewrite從上到下依次執行,並按最後一個匹配成功的做爲最終結果。一種特殊狀況是當replacement中包含http/https等協議名時,直接302跳轉到replacement指定的url,再也不執行後續的rewrite指令。
  那麼若是咱們想在執行一條rewrite指令後再也不執行後續指令怎麼辦呢?這時就能夠用rewrite中的flag標記,四種flag標記均可以實現再也不往下執行其餘rewrite指令的做用,可是每種flag標記的使用場景不一樣。介紹語法的時候已經介紹了四種flag的做用,咱們來看一個栗子吧:
server{
        listen 80;
        server_name www.mysite.com;
        location = /{
                #跳轉到百度
                rewrite ^/(.*) http://www.baidu.com;
           #跳轉到/test1
                rewrite ^/(.*) /test1;
           #跳轉到/test2
                rewrite ^/(.*) /test2;
                root html;
                index index.html;
        }
        location /test1{
                return 401;
        }
        location /test2{
                return 402;
        }

        #日誌記錄
        error_log logs/mysite.error.log error;
        access_log  logs/mysite.access.log  main;
}

  server進行上邊的配置時,咱們訪問虛擬機IP 192.168.70.132,會跳轉到百度頁面,由於replacement包含了http協議名,不在執行後續的rewrite指令;

  若是把第一個rewrite註釋掉,會調整到402錯誤頁,由於rewrite的最終結果時以最後一個匹配成功的爲準,最後匹配到 rewite /test2指令,而後找到location /test2返回402錯誤碼;

  若是咱們在rewrite  ^?(.*)  /test1後邊加上last標記 ,表示再也不匹配後邊的rewrite,會跳到401錯誤頁,url不變仍是http://192.168.70.132;

  若是咱們在rewrite  ^?(.*)  /test1後邊加上redirect 或者 permanent 標記 ,表示再也不匹配後邊的rewrite,會跳轉到401錯誤頁(redirect的跳轉碼爲302,permanet的跳轉碼時301),url會改變成 http://192.168.70.132/test1;

  若是咱們在rewrite  ^?(.*)  /test1後邊加上break標記 ,表示再也不匹配任何規則,會跳轉到404錯誤頁;由於break標記不會再執行任何規則,因此不會再去找location test1,而是直接找 html/test1資源,因此出現404錯誤。

3 一些經常使用的全局變量

  在使用rewrite指令時咱們常常會用到一些經常使用的全局變量,這些全局變量定義在nginx/conf/fastcgi.conf中,列舉以下:
 

變量

含義

$args

請求中的參數,同$query_string

$content length

請求頭中的Content-length字段。

$content_type

請求頭中的Content-Type字段。

$document_root

當前請求在root指令中指定的值。

$host

請求主機頭字段,不然爲服務器名稱。

$http_user_agent

用戶代理,通常爲用戶瀏覽器信息

$http_cookie

客戶端cookie信息

$limit_rate

這個變量能夠限制鏈接速率。

$request_method

客戶端請求的動做,一般爲GET或POST。

$remote_addr

客戶端的IP地址。

$remote_port

客戶端的端口。

$remote_user

已經通過Auth Basic Module驗證的用戶名。

$request_filename

當前請求的文件路徑,由root或alias指令與URI請求生成。

$scheme

協議名(如http,https)。

$server_protocol

請求使用的協議,一般是HTTP/1.0或HTTP/1.1。

$server_addr

服務器地址,在完成一次系統調用後能夠肯定這個值。

$server_name

服務器名稱。

$server_port

請求到達服務器的端口號。

$request_uri

包含請求參數的原始URI,不包含主機名,如」/user/getuser?id=100」。

$uri

不帶請求參數的當前URI,$uri不包含主機名,如」/user/getuser」。

$document_uri

與$uri相同。

這裏列舉幾個rewrite的簡單栗子來幫助理解:

① 禁止特定IP訪問
server{
        listen 80;
        server_name localhost;
        location /{
        #若是客戶端IP是192.168.70.1,那麼拒接響應
           if ($remote_addr = 192.168.70.1){
                 return 403;
           }
           root html;
           index index.html;
        }
}

  經過IP爲192.168.70.1的電腦去訪問時,結果以下:

② 根據瀏覽器不一樣跳轉到不一樣頁面
     #若是是google訪問的,重定向到 html/chrome.html頁面
        location /{
                if ($http_user_agent ~ Chrome){
                        rewrite ^.*$  /chrome.html;
                        break;
                }
                root html;
                index index.html;
        }

③ 文件不存在返回404,寫的比較繁瑣,主要是演示rewrite的用法

server{
        listen 80;
        server_name www.mysite.com;
        location /{
        #若是文件不存在,跳轉到notfound,
                if (!-f  /usr/local/nginx/html/aaa.html){
                        rewrite ^/(.*) /notfound ;
                }
                root html;
                index index.html;
        }
        location ~ /notfound {
                return 404;
        }
        error_log logs/mysite.error.log error;
        access_log  logs/mysite.access.log  main;
}

小結:loaction和rewrite是nginx中最核心的指令,經過location和rewrite咱們能夠實現動靜分離/規範客戶端url等功能,由於支持perl的正則表達式,用法十分靈活。這裏簡單作了一些總結,若是有不正確的地方請指出。

參考文章:

【1】https://www.cnblogs.com/coder-yoyo/p/6346595.html

【2】https://www.cnblogs.com/czlun/articles/7010604.html

【3】https://www.cnblogs.com/crazylqy/p/6892010.html

相關文章
相關標籤/搜索