When using the nginx rewrite (rewrite) mechanism, we usually use last and break. There are a lot of questions about the role of these two commands, and there are a lot of discussions on the Internet, here is a summary: the powerful explanation of netizens: Last: Execute break in the server label after rewrite: Execute the rewrite address in the current location label.
-
Nginx official explanation:
-
last:
-
Stops processing the current set
ngx_http_rewrite_module
Directives followed by a search for a new location matching
-
The changed URI;
-
break:
-
Stops processing the current set
ngx_http_rewrite_module
Directives;
-
In fact, the explanation by netizens is easier to understand. The official explanation of nginx is from the implementation-oriented perspective. Many people may not be too confident in using these two commands, I don't feel at the bottom of my mind. To tell the truth, I felt like this at the beginning. Let's break the sandpot and ask to the end to see how the code is actually implemented. After all, "there is no secret in front of the code".
To facilitate our discussion, we make the following hypothetical Configuration:
location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; return 403;}
Before analysis, the readers should be familiar with the processing of various nginx phase handler and the basic principles of nginx variables. unfamiliar users may seem a little difficult, so the related connections are provided here, those who are not familiar with learning. The first two are about handler, and the last one is about the variable: http://simohayha.iteye.com/blog/670326http://simohayha.iteye.com/blog/679314http://blog.lifeibo.com? P = 346 now go to the topic: In the ngx_http_rewrite function:
If (CF-> ARGs-> nelts = 4) {If (ngx_strcmp (value [3]. data, "last") = 0) {last = 1;} else if (ngx_strcmp (value [3]. data, "break") = 0) {RegEx-> break_cycle = 1; last = 1 ;}... // The remaining processing is omitted}
The focus is on processing last = 1. later:
if (last) { code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ex); if (code == NULL) { return NGX_CONF_ERROR; } *code = NULL;}
LCF-> codes is an array that stores the corresponding operations (various handler) and Data executed by each rewrite. the operation here adds a null value to this array, this NULL is of great significance. In the actual execution of rewrite, for example, the call of ngx_http_rewrite_handler will process the handler placed in this array in advance:
E-> IP = rlcf-> codes-> ELTs ;... // In this while loop, the above null will terminate the execution of a series of rewrite operations. // you can see that, "last" and "break" play the same role in this regard. The current codes array contains the remainder of the // rewrite command, so the existence of null here will skip it. While (* (uintptr_t *) E-> ip) {code = * (ngx_http_script_code_pt *) E-> IP; Code (E );}
For example, in the initial configuration, we wrote:
location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra; return 403;}
That is, if the last and break are not written, the process is to execute these rewrites in sequence and end the request with 403 at the end. In this case, the handler in the Codes array is executed, due to the emergence of last and break, the processing may terminate at a certain position in the middle, and the subsequent rewrite will not be executed. After the rewrite stage is completed, it will be transferred to the find config stage, which was originally prior to the rewrite stage. This process also depicts the basic rewrite process, the URL is changed after the rewrite phase, and one of the key steps for processing a request is to determine the corresponding server conf and location Conf, and find config works exactly like this, after rewriting, the URL can be regarded as a new request, so these key steps need to be repeated. Another problem is the setting of break_cycle in the ngx_http_rewrite function, that is, when break occurs, this variable will be set to 1, and the setting of this variable, in the end, R-> uri_changed will be set to 0, so its direct impact can be seen in the following:// The name of this function is "Post", which means to do some aftercare for rewrite processing ngx_http_core_post_rewrite_phase {// in general, that is, R-> uri_changed> 0, r-> phase_handler is set to pH-> next, // and this pH-> next, which has been set to pH-> next = find_config_index when the phase initialization starts, // In the case of non-break or last, the subsequent phase is the so-called find config stage, but here it is/R-> phase_handler ++, this means that the subsequent processing will be executed, and the process of finding config will not be followed. If (! R-> uri_changed) {r-> phase_handler ++; return ngx_again;}... // other processing parts are omitted here}
For more information about how to set R-> uri_changed to 0, see ngx_http_script_regex_start_code and ngx_http_script_break_code.So here we will summarize: Last is actually equivalent to a new URL, and a request is made to nginx. We need to go through most of the processing processes. The most important thing is to do a find config, it provides an opportunity to switch to the configuration of other locations for processing, and break is a request processing process after the original URL (including Uri and ARGs) is rewritten, after processing continues, all the rewrite requests are always processed in the same location.