溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Last 與 break flag的區別是什么

發布時間:2021-11-09 16:00:57 來源:億速云 閱讀:128 作者:柒染 欄目:建站服務器

Last 與 break flag的區別是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

Rewrite( URL 重寫)指令可以出現在 server{} 下,也可以出現在 location{} 下,它們之間是有區別的!對于出現在 server{} 下的 rewrite 指令,它的執行會在 location 匹配之前;對于出現在 location{} 下的 rewrite 指令,它的執行當然是在 location 匹配之后,但是由于 rewrite 導致 HTTP 請求的 URI 發生了變化,所以 location{} 下的 rewrite 后的 URI 又需要重新匹配 location ,就好比一個新的 HTTP 請求一樣(注意由 location{} 內的 rewrite 導致的這樣的循環匹配最多不超過 10 次,否則 nginx 會報 500 錯誤)??偟膩碚f,如果 server{} 和 location{} 下都有 rewrite ,依然是先執行 server{} ,然后進行 location 匹配,如果被匹配的 location{} 之內還有 rewrite 指令,那么繼續執行 rewrite ,同時因為 location{} 內的 rewrite 改變了 URI ,那么重寫后的結果 URI 需要當做一個新的請求,重新匹配 location (應該也包括重新執行 server{} 下的 rewrite 吧)。

Last 與 break flag 的區別

關于 last flag 和 break flag 的區別,官方文檔的描述是:“ last - completes processing of rewrite directives, after which searches for corresponding URI and location ”和“ break - completes processing of rewrite directives ”,都有“不讓繼續執行后面的 rewrite 指令”的含義,但是兩者的區別并沒有展開。

這里我用實驗來告訴大家區別。實驗準備:

1、  安裝 nginx ;(如果對安裝和 location 不了解的,請參考:http://eyesmore.iteye.com/blog/1141660 )

2、  在 nginx 安裝目錄的 html 子目錄下創建 4 個文件,分別叫: aaa.html , bbb.html , ccc.html 和 ddd.html ,文件內容分別是各自的文件名(例 aaa.html 文件內容不妨寫 aaa html file )。

3、  Nginx 配置文件初始化是:

error_log  logs/error.log info;  #URL 重寫模塊的日志會寫入此文件

   server {

        listen       9090;

        server_name  localhost;

        root html;

        rewrite_log on;   # 打開 URL 重寫模塊的日志開關,以便寫入 error_log

        location  /aaa.html {

            rewrite "^/aaa\.html$"  /bbb.html;

            rewrite "^/bbb\.html$"  /ddd.html;

        }  

        location  /bbb.html {

            rewrite "^/bbb\.html$" /ccc.html;

        }  

}

上述配置注意兩點: 1 、打開 rewrite 模塊的日志開關,以便 rewrite 執行日志寫入 error_log (注: rewrite 日志寫入 error_log 的級別是 notice ,所以要注意 error_log 日志級別,此處用 info ); 2 、定義了兩個 location ,分別是 /aaa.html 和 /bbb.html ,但是在 /aaa.html 中,把 /aaa.html 重寫成 /bbb.html ,接著又把 /bbb.html 重寫成 /ddd.html ;在 /bbb.html 中,把 /bbb.html 重寫成 /ccc.html 。

[ 測試 1] 沒有 last 和 break 標記時:請求 aaa.html

[root@web108 ~]# curl http://localhost:9090/aaa.html

ddd html file

[root@web108 ~]#

Error_log 的日志內容:

2011/08/07 22:13:23 [notice] 9066#0: *85 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:13:23 [notice] 9066#0: *85 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:13:23 [notice] 9066#0: *85 "^/bbb\.html$" matches "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:13:23 [notice] 9066#0: *85 rewritten data: "/ddd.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:13:23 [info] 9066#0: *85 client 127.0.0.1 closed keepalive connection

URL 重寫模塊的日志告訴我們:對于一個 HTTP 請求“ GET /aaa.html ”,重寫過程是:先 /aaa.html 被重寫為 /bbb.html ;然后 rewritten data: /bbb.html ,繼續執行后面的 rewrite 指令,進而被重寫為 /ddd.html ,然后 rewrittern data: /ddd.html 后面沒有重寫了(其實此時 /ddd.html 需要再次重新匹配 location 的,只是日志沒有體現出來,接下來的測試 2 會體現這點),于是輸出 /ddd.html 的內容。

[ 測試 2] 使用 last 標記時:請求 aaa.html

將上述 location /aaa.html {} 修改成:

location  /aaa.html {

       rewrite "^/aaa\.html$"  /bbb.html   last ;

      rewrite "^/bbb\.html$"  /ddd.html;

}  

測試結果:

[root@web108 ~]# curl http://localhost:9090/aaa.html

ccc html file

[root@web108 ~]#

Error_log 日志:

2011/08/07 22:24:31 [notice] 18569#0: *86 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:24:31 [notice] 18569#0: *86 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:24:31 [notice] 18569#0: *86 "^/bbb\.html$" matches "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:24:31 [notice] 18569#0: *86 rewritten data: "/ccc.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:24:31 [info] 18569#0: *86 client 127.0.0.1 closed keepalive connection

不知道讀者看到 GET /aaa.html 顯示的結果“ ccc html file ”會不會驚訝:“為什么結果不是 bbb html file ”。下面解釋下整個過程:首先 /aaa.html 匹配了 location /aaa.html {} ,于是執行 rewrite "^/aaa\.html$"  /bbb.html last ,把 /aaa.html 重寫為 /bbb.html ,同時由于 last flag 的使用,后面的 rewrite 指令(指的是 rewrite "^/bbb\.html$"  /ddd.html )不會被執行。似乎此時應該輸出“ bbb html file ”才對,但是我們看看 nginx 官方解釋:“ last - completes processing of rewrite directives, after which searches for corresponding URI and location ”意思是說 last 不再匹配后面的 rewrite 指令,但是緊接著需要對重寫后的 URI 重新匹配 location 。讓我們再看看官方的“ If the directives of this module are given at the server level, then they are carried out before the location of the request is determined. If in that selected location there are further rewrite directives, then they also are carried out. If the URI changed as a result of the execution of directives inside location, then location is again determined for the new URI. This cycle can be repeated up to 10 times, after which Nginx returns a 500 error. ”因此,重新匹配的時候,匹配到了新的 location /bbb.html {} ,執行“ rewrite "^/bbb\.html$" /ccc.html ”,最后的內容是“ ccc html file ”。

[ 測試 3] 使用 break 標記時:請求 aaa.html

將上述 location /aaa.html {} 修改成使用 break 標記:

location  /aaa.html {

      rewrite "^/aaa\.html$"  /bbb.html  break ;

      rewrite "^/bbb\.html$"  /ddd.html;

}  

測試結果:

[root@web108 ~]# curl http://localhost:9090/aaa.html

bbb html file

[root@web108 ~]#

日志結果:

2011/08/07 22:37:49 [notice] 21069#0: *89 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:37:49 [notice] 21069#0: *89 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/07 22:37:49 [info] 21069#0: *89 client 127.0.0.1 closed keepalive connection

我想這個結果不用多做解釋了,充分體現了 break 和 last 的區別:“ last - completes processing of rewrite directives, after which searches for corresponding URI and location ”和“ break - completes processing of rewrite directives ”。 Break 和 last 都能阻止繼續執行后面的 rewrite 指令,但是 last 如果在 location 下用的話,對于重寫后的 URI 會重新匹配 location ,但是 break 則不會重新匹配 location 。簡單的說, break 終止的力度比 last 更加徹底(為了記憶的方便,我們可以把重新后的 URI 重新匹配 location 理解為“ URI 匹配 location 的循環語句的下一次迭代”,高級程序設計里面 break 一般用做退出循環,所以 break 不僅終止繼續執行 rewrite ,而且退出 URI 重新匹配 location 的循環迭代)。

Nginx 關于 Rewrite 的迭代 第二篇

例題 1

配置:

error_log  logs/error.log info;

server {

        listen       9090;

        server_name  localhost;

        root html;

        rewrite_log on;

        rewrite "^/aaa\.html$"  /bbb.html;

        location  /ccc.html {

            rewrite "^/ccc\.html$"  /eee.html;

        }

        location  /bbb.html {

            rewrite "^/bbb\.html$" /ccc.html;

            rewrite "^/ccc\.html$" /ddd.html;

        }  

}   

結果:

[root@web108 ~]# curl http://localhost:9090/aaa.html

ddd html file

[root@web108 ~]#

日志:

2011/08/08 10:05:41 [notice] 31592#0: *90 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [notice] 31592#0: *90 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [notice] 31592#0: *90 "^/bbb\.html$" matches "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [notice] 31592#0: *90 rewritten data: "/ccc.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [notice] 31592#0: *90 "^/ccc\.html$" matches "/ccc.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [notice] 31592#0: *90 rewritten data: "/ddd.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [notice] 31592#0: *90 "^/aaa\.html$" does not match "/ddd.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:05:41 [info] 31592#0: *90 client 127.0.0.1 closed keepalive connection

解釋:

GET /aaa.html 請求,首先執行 server 級的 rewrite 指令,被重寫為 /bbb.html ,然后匹配到 location /bbb.html {} ,接著執行 location 級的 rewrite 指令,先重寫為 /ccc.html ,再重寫為 /ddd.html ;由于 URI 被 location 級的 rewrite 指令重寫了,因此需要重新進行 location 的匹配,相當于重寫后的 URI 被當做一個新的請求,會重新執行 server 級的 rewrite ,然后重新匹配 location ,日志“ 2011/08/08 10:05:41 [notice] 31592#0: *90 "^/aaa\.html$" does not match "/ddd.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090" ”體現了重新匹配 location 的流程。

例題 2

配置:

error_log  logs/error.log info;

server {

        listen       9090;

        server_name  localhost;

        root html;

        rewrite_log on;

        rewrite "^/aaa\.html$"  /bbb.html;

                   rewrite "^/ccc\.html$"  /ddd.html;

        location  /bbb.html {

            rewrite "^/bbb\.html$" /ccc.html;

        }  

                   location  /ddd.html {

             rewrite "^/ddd\.html$" /eee.html;

        }

}   

結果:

[root@web108 ~]# curl http://localhost:9090/aaa.html

eee html file

[root@web108 ~]#

日志:

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/aaa\.html$" matches "/aaa.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/bbb.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ccc\.html$" does not match "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/bbb\.html$" matches "/bbb.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/ccc.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/aaa\.html$" does not match "/ccc.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ccc\.html$" matches "/ccc.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/ddd.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ddd\.html$" matches "/ddd.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 rewritten data: "/eee.html" , args: "", client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/aaa\.html$" does not match "/eee.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [notice] 2218#0: *91 "^/ccc\.html$" does not match "/eee.html" , client: 127.0.0.1, server: localhost, request: "GET /aaa.html HTTP/1.1", host: "localhost:9090"

2011/08/08 10:21:00 [info] 2218#0: *91 client 127.0.0.1 closed keepalive connection

解釋:

第一次迭代 location 匹配

GET /aaa.html ,首先執行 server 級的重寫,“ rewrite "^/aaa\.html$"  /bbb.html ”把 /aaa.html 重寫為 /bbb.html ,但 /bbb.html 沒匹配上“ rewrite "^/ccc\.html$"  /ddd.html ”,最終保留 /bbb.html ;接著,匹配 location /bbb.html {} ,執行 location 級的 rewrite 指令,把 /bbb.html 重寫為 /ccc.html ,由于 URI 被 location 級 rewrite 重寫,因此需要重新迭代 location 匹配。

第二次迭代 location 匹配

對于第一次迭代結果 /ccc.html ,首先依然是執行 server 級的 rewrite 指令,“ rewrite "^/aaa\.html$"  /bbb.html; ”跟 /ccc.html 不匹配,但“ rewrite "^/ccc\.html$"  /ddd.html; ”把 /ccc.html 重寫為 /ddd.html ; server 級 rewrite 執行完后,接著 location 匹配, /ddd.html 匹配到 location /ddd.html {} ,執行 location 級的 rewrite 指令,把 /ddd.html 重寫為 /eee.html 。同樣由于 URI 被 location 級的 rewrite 指令重寫,于是需要重新迭代 location 匹配。

第三次迭代 location 匹配

對于第二次迭代結果 /eee.html ,首先依然執行 server 級的 rewrite 指令,“ rewrite "^/aaa\.html$"  /bbb.html; ”和“ rewrite "^/ccc\.html$"  /ddd.html; ”,只不過它們都沒匹配上 /eee.html ,接著 /eee.html 進行 location 匹配,也沒有,最終結果是 /eee.html ,返回“ eee html file ”頁面。

最后說明下,如果把上述配置修改成server級rewrite和location的編輯順序調整:

server {
        listen       9090;
        server_name  localhost;
        root html;
        rewrite_log on;

               
        location  /bbb.html {
            rewrite "^/bbb\.html$" /ccc.html;
        }   
        location  /ddd.html {
            rewrite "^/ddd\.html$" /eee.html;
        }

        rewrite "^/aaa\.html$"  /bbb.html;
        rewrite "^/ccc\.html$"  /ddd.html;
}

結果是不會受影響的,也就是說location匹配迭代總是先執行server級rewrite,再進行location匹配,再執行location級的rewrite,如果URI因location級rewrite指令重寫,則需要進行下一次迭代。但總的迭代次數不超過10次,否則nginx報500錯誤。

簡單偽代碼描述下rewrite執行過程:

boolean match_finish = false;
int match_count = 0;
while(!match_finish && match_count < 10) {
        match_count ++;
    (1)按編輯順序執行server級的rewrite指令;
    (2)按重寫后的URI匹配location;
    (3)
        String uri_before_location = uri;
        按編輯順序執行location級的rewrite指令;
        String uri_after_location = rewrite(uri);
        if(uri_before_location != uri_after_location) {
            match_finish = false;            
        } else {
            match_finish = true;
        }
        if(location rewrite has last flag) {
            continue;//表示不執行后面的rewrite,直接進入下一次迭代
        }
        if(location rewrite has break flag) {
            break;//表示不執行后面的rewrite,并退出循環迭代
        }
}
if(match_count <= 10) {
    return HTTP_200;
} else {
    return HTTP_500;
}

關于Last 與 break flag的區別是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女