nginx 配置文件中经常会用到last与break指令。那么两者之间的区别如何呢?
以nginx-1.0.14的源码为例:
/src/http/modules/ngx_http_rewrite_module.c (366-389行)
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 ;
} else if (ngx_strcmp (value [ 3 ]. data , "redirect" ) == 0 ) {
regex ->status = NGX_HTTP_MOVED_TEMPORARILY ;
regex ->redirect = 1 ;
last = 1 ;
} else if (ngx_strcmp (value [ 3 ]. data , "permanent" ) == 0 ) {
regex ->status = NGX_HTTP_MOVED_PERMANENTLY ;
regex ->redirect = 1 ;
last = 1 ;
} else {
ngx_conf_log_error (NGX_LOG_EMERG , cf , 0 ,
"invalid parameter \"%V\"" , &value [ 3 ] ) ;
return NGX_CONF_ERROR ;
}
}
break 与last的区别在于多了一行,regex->break_cycle = 1; 那么我们来看看这行语句具体有何含义。
break_cycle赋值后会被ngx_http_script_regex_code_t *code 调用。
具体在/src/http/ngx_http_script.c (1007行),代码段如下:
if (code ->break_cycle ) {
r->valid_location = 0;
r->uri_changed = 0;
} else {
r ->uri_changed = 1 ;
}
r->valid_location = 0; 表示break指令不会继续作用于之后的location域。
r->uri_changed = 0;表示break指令停止继续匹配。而last指令会继续匹配下去。
继续看如下代码
/src/http/ngx_http_core_module.c(1038行)
ngx_http_core_post_rewrite_phase (ngx_http_request_t *r ,
ngx_http_phase_handler_t *ph )
{
ngx_http_core_srv_conf_t *cscf ;
ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r ->connection -> log , 0 ,
"post rewrite phase: %ui" , r ->phase_handler ) ;
if ( !r ->uri_changed ) {
r ->phase_handler ++;
return NGX_AGAIN ;
}
r->uri_changed = 0; 内核会跳出处理下一个请求。
last指令 r->uri_changed = 1; 会继续不停的匹配。
总结:使用break指令后,不会继续作用于随后的location域,不会循环继续匹配。last指令恰恰相反。
从效率上来说尽量使用break指令。