1. 程式人生 > >nginx rewrite 指令last break區別

nginx rewrite 指令last break區別

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執行有11個執行階段,上面說提到的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階段,並繼續執行本請求的其他階段,很明顯,對於/break 對應的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;

訪問 /testtest/的時候,輸出的值是/test.php的內容,顯然,重寫到rewrite上了,交換rewrite和location位置,執行結果不變,說明這個和位置無關

參考:http://blog.51cto.com/tenderrain/1949254