天天看點

nginx rewrite 指令last break差別最詳細的解釋

總結: rewrite 可以在 server location 塊, 正則比配的時候才重寫,是以多條 rewrite 順序靠前且比對的優先執行。

break跳出rewrite階段,不會在比對,進入輸出階段。 last 類似重新發起請求,是以會重新進行比對。

轉自:http://blog.sina.com.cn/s/blog_4f9fc6e10102ux0w.html

http://blog.cafeneko.info/2010/10/nginx_rewrite_note/ 或者 http://yuanhsh.iteye.com/blog/1321982

nginx 的官方注釋是這樣的:

last
   stops processing the current set of ngx_http_rewrite_module directives followed by a search for a new location matching the changed URI;

break
   stops processing the current set of ngx_http_rewrite_module directives;      

我們知道nginx運作分十一個執行階段,上面說提到的ngx_http_rewrite_mode,可以了解為其中一個階段-rewrite階段。

typedef enum {
    NGX_HTTP_POST_READ_PHASE = 0,
    NGX_HTTP_SERVER_REWRITE_PHASE,
    NGX_HTTP_FIND_CONFIG_PHASE,
    NGX_HTTP_REWRITE_PHASE,           //rewrite階段在這裡
    NGX_HTTP_POST_REWRITE_PHASE,
    NGX_HTTP_PREACCESS_PHASE,
    NGX_HTTP_ACCESS_PHASE,
    NGX_HTTP_POST_ACCESS_PHASE,
    NGX_HTTP_TRY_FILES_PHASE,
    NGX_HTTP_CONTENT_PHASE,
    NGX_HTTP_LOG_PHASE
} ngx_http_phases;      

是以我們再來了解last與break的差別:

last: 停止目前這個請求,并根據rewrite比對的規則重新發起一個請求。新請求又從第一階段開始執行…

break:相對last,break并不會重新發起一個請求,隻是跳過目前的rewrite階段,并執行本請求後續的執行階段…

我們來看一個例子:

server {
    listen 80 default_server;
    server_name dcshi.com;
    root www;

    location /break/ {
        rewrite ^/break/(.*) /test/$1 break;
        echo "break page";
    } 

    location /last/ {
         rewrite ^/last/(.*) /test/$1 last;
         echo "last page";
    }    

    location /test/ {
       echo "test page";
    }
}      

請求:http://dcshi.com/break/***

輸出: break page

分析:正如上面讨論所說,break是跳過目前請求的rewrite階段,并繼續執行本請求的其他階段,很明顯,對于/foo 對應的content階段的輸出為 echo “break page”; (content階段,可以簡單了解為産生資料輸出的階段,如傳回靜态頁面内容也是在content階段;echo指令也是運作在content階段,一般情況下content階段隻能對應一個輸出指令,如同一個location配置兩個echo,最終隻會有一個echo指令被執行);當然如果你把/break/裡的echo 指令注釋,然後再次通路/break/xx會報404,這也跟我們預期一樣:雖然/break/xx被重定向到/test/xx,但是break指令不會重新開啟一個新的請求繼續比對,是以nginx是不會比對到下面的/test/這個location;在echo指令被注釋的情況下,/break/ 這location裡隻能執行nginx預設的content指令,即嘗試找/test/xx這個html頁面并輸出起内容,事實上,這個頁面不存在,是以會報404的錯誤。

請求: http://dcshi.com/last/***

輸出: test page

分析: last與break最大的不同是,last會重新發起一個新請求,并重新比對location,是以對于/last,重新比對請求以後會比對到/test/,是以最終對應的content階段的輸出是test page;

假設你對nginx的運作階段有一個大概的了解,對了解last與break就沒有問題了。

location ~ ^/testtest/ {

default_type text/html;

echo 111;

}

rewrite ^/testtest/  /test.php last;